C++之动态链接库
[TOC]
什么是动态链接库?(Dynamic Link Library,DLL)
动态链接库(Dynamic Link Library)DLL文件与EXE文件一样也是可执行文件,但是DLL也被称之为库,因为里面封装了各种类啊,函数啊之类的东西,就像是一个库一样,存储着很多东西,主要是用来调用的。调用方式主要分为两种:隐式(通过lib文件与头文件) 与 显式(只通过DLL文件)。
C++的入口函数
dll的入口函数,简而言之,就是只在dll被load的时候调用一次,之后都不会被调用,也无法在dll外部被调用。
并且同一个dll,被多个进程load多次,内存中也只会有此动态链接库的一个副本,也只会加载一次入口函数。(由动态链接库的属性决定)
C++的导出函数
- C++的代码示例
1 | //dll.h |
1 | //dll.cpp |
- __stdcall是函数调用约定的一种,常见的函数调用约定:stdcall cdecl fastcall thiscall naked call,函数调用约定主要约束了两件事:
- 参数传递顺序
- 调用堆栈由谁(调用函数或被调用函数)清理
- __stdcall表示
- 参数从右向左压入堆栈
- 函数被调用者修改堆栈
- 函数名(在编译器这个层次)自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸
在win32应用程序里,宏APIENTRY,WINAPI,都表示_stdcall,非常常见。
-
extern “C”
的主要作用就是为了能够正确实现C代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言(而不是C)的方式进行编译。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。此处为的是直接将函数名直接导出,在C#调用时不用在单独指明入口点。
这个功能十分有用处,因为在C出现以前,很多代码都是C语言写的,而且很底层的库也是C语言写的,为了更好的支持原来的C代码和已经写好的C语言库,需要在C中尽可能的支持C,而extern "C"就是其中的一个策略。
这个功能主要用在下面的情况:
- C++代码调用C语言代码
- 在C++的头文件中使用
- 在多个人协同开发时,可能有的人比较擅长C语言,而有的人擅长C++,这样的情况下也会有用到
-
__declspec(dllexport)与__declspec(dllimport)
他们都是DLL内的关键字,即导出与导入。他们是将DLL内部的类与函数以及数据导出与导入时使用的。
dllexport是在这些类、函数以及数据的申明的时候使用。用他表明这些东西可以被外部函数使用,即(dllexport)是把 DLL中的相关代码(类,函数,数据)暴露出来为其他应用程序使用。使用了(dllexport)关键字,相当于声明了紧接在(dllexport)关键字后面的相关内容是可以为其他程序使用的。
dllimport是在外部程序需要使用DLL内相关内容时使用的关键字。当一个外部程序要使用DLL 内部代码(类,函数,全局变量)时,只需要在程序内部使用(dllimport)关键字声明需要使用的代码就可以了,即(dllimport)关键字是在外部程序需要使用DLL内部相关内容的时候才使用。(dllimport)作用是把DLL中的相关代码插入到应用程序中。
_declspec(dllexport)与_declspec(dllimport)是相互呼应,只有在DLL内部用dllexport作了声明,才能在外部函数中用dllimport导入相关代码。
-
通过DLL Export Viewer 查看生成的导出函数如下所示
C#中通过PInvoke调用DLL
通过C#的互操作类可以导入外部函数以供程序调用,调用方式如下所示,
1 | using System; |
C++与C#中的类型匹配
C++ | C# |
---|---|
BOOL | System.Int32 |
BOOLEAN | System.Int32 |
BYTE | System.UInt16 |
CHAR | System.Int16 |
COLORREF | System.UInt32 |
- | - |
DWORD | System.UInt32 |
DWORD32 | System.UInt32 |
DWORD64 | System.UInt64 |
FLOAT | System.Float |
HACCEL | System.IntPtr |
- | - |
HANDLE | System.IntPtr |
HBITMAP | System.IntPtr |
HBRUSH | System.IntPtr |
HCONV | System.IntPtr |
HCONVLIST | System.IntPtr |
- | - |
HCURSOR | System.IntPtr |
HDC | System.IntPtr |
HDDEDATA | System.IntPtr |
HDESK | System.IntPtr |
HDROP | System.IntPtr |
- | - |
HDWP | System.IntPtr |
HENHMETAFILE | System.IntPtr |
HFILE | System.IntPtr |
HFONT | System.IntPtr |
HGDIOBJ | System.IntPtr |
- | - |
HGLOBAL | System.IntPtr |
HHOOK | System.IntPtr |
HICON | System.IntPtr |
HIMAGELIST | System.IntPtr |
HIMC | System.IntPtr |
- | - |
HINSTANCE | System.IntPtr |
HKEY | System.IntPtr |
HLOCAL | System.IntPtr |
HMENU | System.IntPtr |
HMETAFILE | System.IntPtr |
- | - |
HMODULE | System.IntPtr |
HMONITOR | System.IntPtr |
HPALETTE | System.IntPtr |
HPEN | System.IntPtr |
HRGN | System.IntPtr |
- | - |
HRSRC | System.IntPtr |
HSZ | System.IntPtr |
HWINSTA | System.IntPtr |
HWND | System.IntPtr |
INT | System.Int32 |
- | - |
INT32 | System.Int32 |
INT64 | System.Int64 |
LONG | System.Int32 |
LONG32 | System.Int32 |
LONG64 | System.Int64 |
- | - |
LONGLONG | System.Int64 |
LPARAM | System.IntPtr |
LPBOOL | System.Int16[] |
LPBYTE | System.UInt16[] |
LPCOLORREF | System.UInt32[] |
- | - |
LPCSTR | System.String |
LPCTSTR | System.String |
LPCVOID | System.UInt32 |
LPCWSTR | System.String |
LPDWORD | System.UInt32[] |
- | - |
LPHANDLE | System.UInt32 |
LPINT | System.Int32[] |
LPLONG | System.Int32[] |
LPSTR | System.String |
LPTSTR | System.String |
- | - |
LPVOID | System.UInt32 |
LPWORD | System.Int32[] |
LPWSTR | System.String |
LRESULT | System.IntPtr |
PBOOL | System.Int16[] |
- | - |
PBOOLEAN | System.Int16[] |
PBYTE | System.UInt16[] |
PCHAR | System.Char[] |
PCSTR | System.String |
PCTSTR | System.String |
- | - |
PCWCH | System.UInt32 |
PCWSTR | System.UInt32 |
PDWORD | System.Int32[] |
PFLOAT | System.Float[] |
PHANDLE | System.UInt32 |
- | - |
PHKEY | System.UInt32 |
PINT | System.Int32[] |
PLCID | System.UInt32 |
PLONG | System.Int32[] |
PLUID | System.UInt32 |
- | - |
PSHORT | System.Int16[] |
PSTR | System.String |
PTBYTE | System.Char[] |
PTCHAR | System.Char[] |
PTSTR | System.String |
- | - |
PUCHAR | System.Char[] |
PUINT | System.UInt32[] |
PULONG | System.UInt32[] |
PUSHORT | System.UInt16[] |
PVOID | System.UInt32 |
- | - |
PWCHAR | System.Char[] |
PWORD | System.Int16[] |
PWSTR | System.String |
REGSAM | System.UInt32 |
SC_HANDLE | System.IntPtr |
- | - |
SC_LOCK | System.IntPtr |
SHORT | System.Int16 |
SIZE_T | System.UInt32 |
SSIZE_ | System.UInt32 |
TBYTE | System.Char |
- | - |
TCHAR | System.Char |
UCHAR | System.Byte |
UINT | System.UInt32 |
UINT32 | System.UInt32 |
UINT64 | System.UInt64 |
- | - |
ULONG | System.UInt32 |
ULONG32 | System.UInt32 |
ULONG64 | System.UInt64 |
ULONGLONG | System.UInt64 |
USHORT | System.UInt16 |
- | - |
WORD | System.UInt16 |
WPARAM | System.IntPtr |