在第一篇技术博客"动态连接库简介"中说到了两种加载方式,当时没有详细说明,这里详细说明一下ide
能够经过两种方式函数
1.隐式连接(须要.dll,.lib,.h)测试
2.显式连接(须要.dll,.h)spa
隐式连接就是在程序开始执行时就将DLL文件加载到内存当中,而显示连接,是实时加载,程序须要的时候加载,不须要的时候,卸载。指针
这种方式须要DLL文件,以及相应的Lib文件和头文件。blog
只要没有在程序中显式连接的,都是隐式连接内存
Windows程序bin目录包含了可执行文件(.exe)和动态连接库(.dlll),lib目录包含了静态库。get
第一步:将.dll,lib,.h文件放入对应的搜索路径
●其中动态库的搜索路径点击这里查看,记住最重要的两个
1、项目当前目录(.cpp)目录
2、path环境变量中的目录博客
●静态库的搜索路径包括
1、项目当前目录.cpp目录(项目和解决方案的Debug不行)(也不是解决方案目录)
2、VC设置中的库目录(Library Directories)it
注:若是lib库不放到搜索路径中,也能够在程序中添加
#pragmacomment(lib,"D:/DLLTest.lib")//如果相对路径,则为项目当前.cpp目录
●头文件搜索路径包括
1、VC设置中的包含目录(Include Directories)
第二步:必定要在VC设置中的依赖项中添加你用到的库的名字
设置.dll,.lib搜索路径:直接将.dll,.lib,.h放入项目当前目录下(即含有项目源文件.cpp的目录)
设置.h的搜索路径:VC设置中的包含目录(Include Directories)加入你的.h路径
而后在连接->输入->附加依赖项中加入你要使用的静态库。
这里只添加静态库
就可使用DLL中的函数了。
如Opencv,OSG等开源库的配置
这种方式也是一般开源库的配置方式,如Opencv,OSG等
步骤以下
方法1:★将dll目录(一般为bin目录)放入环境变量Path中(须要重启),path是搜索动态库的目录
在工程中的VC++目录中添加静态库目录和头文件目录。
在连接->输入->附加依赖项中加入你要使用的静态库(当程序中调用时,会在上述配置的库目录中寻找这个库)。
这里只添加静态库,动态库的目录已放入环境变量中,系统会搜索这个路径的,自动加载.dll
如RmwRoadBoundaryStraightLineDLL.lib
而后,在程序中添加头文件 (在上述配置的头文件目录中寻找),就可使用DLL中的函数了。
就是显式加载DLL库
注意:显示连接,导出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,"函数名");
而不是简单的“Add”,由于DLL中的函数名是结果VC++方式处理过的函数名
显示调用,最好采用extern “C”的方式导出DLL
因此采用隐式连接方式的时候,只加载须要的DLL,在附加依赖项中,只添加须要的DLL对于的lib,不要多加,不然会形成1.加大程序启动时间 2.内存浪费
参考文献
1、《C++ Primer》(第4版 特别版)
2、《VC++深刻详解》孙鑫