C++中书写和调用DLL

流过昼夜 提交于 2020-02-07 13:22:43

DLL书写

import和export

头文件由于不参与编译,所以一定要注意区分是在什么时候引用的。如果是在定义函数/类的源文件中使用(内部编译),则要使用__declspec(dllexport),指明要输出在生成的dll文件中的函数/类。但若在引用该DLL的文件中使用(外部引用),包含的头文件中应为__declspec(dllimport),指明要从对应的DLL文件中引入哪些函数/类。

头文件中最开始的宏定义往往如下,注意DLL_EXPORT最好更换为更特别的名字,以防引用该库的文件中也定义了该宏:

#ifdef DLL_EXPORT
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

为了成功编译,还要在预编译的头文件中预先定义DLL_EXPORT,同时在对应的DLL源文件中添加#define DLL_EXPORT __declspec(dllexport)

DLL的使用

隐式链接

DLL程序书写完毕后编译后会在DEBUG文件夹下生成对应的.dll和.lib文件。新的项目若想引用该dll,则需要进行如下操作:

  • 将.h头文件引入包含目录,并在需要使用dll库中函数/类的源文件中include该头文件;
  • 引入Lib文件:
    • .lib文件引入库目录,并且在“链接器->输入->依赖项”中添加对应的.lib文件;
    • #pragma comment (lib,"*.lib")加入预编译指令,添加对应lib文件;
  • 编译链接,生成可执行文件,将.dll文件拷贝至.exe同一文件夹下;
显式链接

该方法需要通过编码完成,较复杂,但能指定DLL文件位置,不需要DLL文件一定与exe文件在同一个文件夹下。具体操作如下:

  • 定义DLL句柄,使用LoadLibrary(L"/path/to/*.DLL")函数加载对应DLL;
  • 定义对应的函数指针,以接纳DLL库中对应的函数;
  • 使用GetProcAddress(DLL_Handle, Function_Name)寻找该dll中对应名称的函数指针,此处应注意进行编译时,不同的编译器对函数名称会有一定方式的处理。C++由于支持函数重载,故函数名中会以一定规则添加参数列表中参数的属性。而C不支持重载,故仅仅是函数名。这也就是为何在编写DLL程序时往往在函数前添加extern "C"的缘故,添加了这个前缀的函数才会按照C编译器规则,直接将函数名称原封不动地编译。另外一种方式就是通过MAKEINTRESOURCEA(int)代替Function_Name,直接指定寻找第几个函数;
  • 使用函数指针调用相应的函数,注意使用前判空;

代码示例:

typedef int(*pAdd)(int, int); //宏定义函数指针类型
HINSTANCE hDll; //DLL句柄 
pAdd addFun; //函数指针
pAdd subFun; //函数指针
hDll = LoadLibrary(L"/path/to/Dll1.dll"); // 加载DLL
if (hDll != NULL)
{
    addFun = (pAdd)GetProcAddress(hDll, "add");  // 通过名称搜索dll库中的add函数赋值给addFun,注意不同编译器的名称处理
    subFun = (pAdd)GetProcAddress(hDll, MAKEINTRESOURCEA(2));  // 通过顺序搜索dll库中的第2个函数赋值给subFun
    if (addFun != NULL){
        cout << "3 + 2 = " << addFun(3, 2) << endl;
    } else {
        cout << "Couldn't Found Function whose name is 'add'" << endl;
    }
    if (subFun != NULL){
        cout << "3 - 2 = " << subFun(3, 2) << endl;
    } else {
        cout << "Couldn't Found the 2nd Function" << endl;
    }

    FreeLibrary(hDll);  // 使用完毕后一定注意关闭资源

} else {
    cout << "Couldn't Found DLL file - DLL1.dll" << endl;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!