动态链接库dll的两种加载方式

在第一篇技术博客"动态链接库简介"中说到了两种加载方式,当时没有详细说明,这里详细说明一下

可以通过两种方式

     1.隐式链接(需要.dll,.lib,.h)

        2.显式链接(需要.dll,.h)

方法1:隐式链接----需要.lib.dll.h文件

 

隐式链接就是在程序开始执行时就将DLL文件加载到内存当中,而显示链接,是实时加载,程序需要的时候加载,不需要的时候,卸载。

这种方式需要DLL文件,以及相应的Lib文件和头文件

 

只要没有在程序中显式链接的,都是隐式链接

 

Windows程序bin目录包含了可执行文件(.exe)和动态链接库(.dlll),lib目录包含了静态库

步骤

第一步:将.dll,lib,.h文件放入对应的搜索路径
      
●其中动态库的搜索路径点击这里查看,记住最重要的两个
             
1、项目当前目录(.cpp)目录
              2
path环境变量中的目录

       ●静态库的搜索路径包括
              1
项目当前目录.cpp目录(项目和解决方案的Debug不行)(也不是解决方案目录)
              2
VC设置中的库目录(Library Directories)

wKiom1QCrPPAhtguAABUIFJfVj4365.jpg

注:如果lib库不放到搜索路径中,也可以在程序中添加

             #pragmacomment(lib,"D:/DLLTest.lib")//若是相对路径,则为项目当前.cpp目录

       头文件搜索路径包括
              1
VC设置中的包含目录(Include Directories)

wKioL1QCrgqxNCLnAABfcSNujig200.jpg

第二步:一定要在VC设置中的依赖项中添加你用到的库的名字

wKiom1QCrPPgJ2ncAACcllno2sw139.jpg

第一种(对应上面每种搜索路径1):针对数量较少的库

设置.dll,.lib搜索路径:直接将.dll,.lib,.h放入项目当前目录下(即含有项目源文件.cpp的目录)

wKioL1QCrgqSH4rIAAKnYpg6FNo833.jpg

设置.h的搜索路径:VC设置中的包含目录(Include Directories)加入你的.h路径

然后在链接->输入->附加依赖项中加入你要使用的静态库。

这里只添加静态库



wKiom1QCrPORqDOIAAM4IWin4Ao267.jpg



就可以使用DLL中的函数了。

 

第二种(对应上面每种搜索路径2):针对数量比较多的库(Opencv)

Opencv,OSG等开源库的配置

这种方式也是通常开源库的配置方式,Opencv,OSG

步骤如下

步骤1.添加DLL的目录

       方法1dll目录(通常为bin目录)放入环境变量Path(需要重启)path是搜索动态库的目录

步骤2.添加静态库lib库目录和头文件的目录

在工程中的VC++目录中添加静态库目录和头文件目录

wKioL1QCrguS-J6-AAN0P0KRB7A809.jpg


步骤3.添加静态库

在链接->输入->附加依赖项中加入你要使用的静态库(当程序中调用时,会在上述配置的库目录中寻找这个库)

这里只添加静态库,动态库的目录已放入环境变量中,系统会搜索这个路径的,自动加载.dll

RmwRoadBoundaryStraightLineDLL.lib


然后,在程序中添加头文件 (在上述配置的头文件目录中寻找),就可以使用DLL中的函数了。


方法2:显式链接---需要DLL(不需要.lib,.h文件)

就是显式加载DLL

wKioL1QCrguB9C3yAAHL_WjDxyg976.jpg

wKiom1QCrPTB0AWmAAOXuLDq8io704.jpg

wKioL1QCrgyTN_cpAAJEsq00lLc798.jpg


注意:显示链接,导出DLL的时候,采用extern “C”的方式,而不采用_declspec(dllexport),因为_declspec(dllexport)会有一个名字改编的问题(采用了_cdecl调用规约的C++编译方式)

示例:

 

如库文件对应的头文件如下

#ifndef DLLTEST_H

#defineDLLTEST_H

 

//该宏完成在dll项目内部使用__declspec(dllexport)导出

//dll项目外部使用时,用__declspec(dllimport)导入

//DLL_EXPORTS.cpp中定义

#ifdefDLL_EXPORTS

#defineDLL_EXPORTS extern"C"_declspec(dllexport)

#else

#define DLL_EXPORTS extern"C"_declspec(dllimport)

#endif

//函数声明

DLL_EXPORTSint  Add(int a,int b);

DLL_EXPORTSint  Sub(int a,int b);

DLL_EXPORTSint  Divide(int a,int b);

#endif//DLLTEST_H

 

 

测试代码:

       typedefint(*Add)(int a, int b);

      typedefint(*Sub)(int a, int b);

      HINSTANCE hDLL;

      Add Add_;//函数指针

       hDLL =LoadLibrary(_T("D:/DLLTest.dll"));//加载动态链接库DLLTest.dll文件;

       Add_ = (Add)GetProcAddress(hDLL,"Add");

      intresult = Add_(5, 8);

       printf("5+8:%d\n",result);

       FreeLibrary(hDLL);//卸载.dll文件;

 

以下是采用__declspec(dllexport)方式导出,不推荐这种方式需要注意函数名的书写问题!

现在DLLTest.h中有函数(采用__declspec(dllexport)方式导出)

#ifndef DLLTEST_H

#defineDLLTEST_H

 

//该宏完成在dll项目内部使用__declspec(dllexport)导出

//dll项目外部使用时,用__declspec(dllimport)导入

//DLL_EXPORTS.cpp中定义

#ifdefDLL_EXPORTS

#defineDLL_EXPORTS __declspec(dllexport)

#else

#define DLL_EXPORTS __declspec(dllimport)

#endif

 

 

intDLL_EXPORTS Add(int a,int b);

intDLL_EXPORTS Sub(int a,int b);

intDLL_EXPORTS Divide(int a,int b);

 

#endif//DLLTEST_H

 

测试代码

       typedefint(*Add)(int a, int b);

      typedefint(*Sub)(int a, int b);

      HINSTANCE hDLL;

      Add Add_;//函数指针

       //也可以采用hDLL =LoadLibrary(_T("D:/DLLTest.dll"));

       hDLL =LoadLibraryA(("D:/DLLTest.dll"));//加载动态链接库DLLTest.dll文件;

 

Add_ = (Add)GetProcAddress(hDLL,"?Add@@YAHHH@Z");//!!!!获取函数地址

      intresult = Add_(5, 8);

       printf("5+8:%d\n",result);

       FreeLibrary(hDLL);//卸载.dll文件;

这里需要注意的是:GetProcAddress(hDLL,"函数名");中的函数名要是DLL中的函数名,这个函数名可以用PE Explorer软件查看

由于采用的是VC++处理函数名方式,所以

GetProcAddress(hDLL,"?Add@@YAHHH@Z");// GetProcAddress(hDLL,"函数名");


wKiom1QCrPWy97AQAACg59nalXs720.jpg

而不是简单的“Add”,因为DLL中的函数名是结果VC++方式处理过的函数名

显示调用,最好采用extern “C”的方式导出DLL

wKioL1QCrgzDSEVOAAc-IvtlRq4253.jpg

所以采用隐式链接方式的时候,只加载需要的DLL在附加依赖项中,只添加需要的DLL对于的lib,不要多加,否则会造成1.加大程序启动时间 2.内存浪费


参考文献

1、《C++ Primer(4特别版)

2、《VC++深入详解》孙鑫

  • 11
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值