随手笔记之VC++(五)

来源:互联网 发布:unity3d往复运动 编辑:程序博客网 时间:2024/04/30 08:53

静态库和动态库:

静态库扩展名一般为.Lib, 在编译连接时候会把其中要调用的函数和数据复制出来和应用模块组合起来,组合成最终可执行的文件,当发布产品的时候只需要发布可执行文件,不需要发布静态库。

动态库的使用时候,要提供两个文件,一个是引入库,.lib,一个是DLL .dll

引用库虽然和静态库后缀名一样但是本质不同,引入库包含了DLL导出的函数和变量的符号名,而.dll 则是包含了实际的数据和函数,编译连接的时候加入引入库.libDLL中的函数和数据不被复制,只是最终执行的时候才去要加载所需的DLL,将该DLL映射到进程的地址空间去,而后访问DLL中导出的函数,发布产品的时候还要发布该程序要调用的DLL

使用动态链接看的好处:

1. 可以采用多种编程语言来编程。

2. 增强产品的功能。

3. 提供二次开发的平台。

4. 简化项目管理。

5. 可以节省磁盘和内存空间。

6. 有助于资源的共享。

为了让DLL 导出一些函数,需要在每一个将要被导出的函数前面添加标示符,:_declspec(dllexport)  如:

_declspec(dllexport) int add(int  a, int  b)

{

  Return a+b;

}

可以用Dumpbin 命令来查看DLL 有哪些导出函数。在DLL 文件夹下:

Dumpbin –exports  xxx.dll

使用动态链接库的导出函数方法:

1. 在调用函数之前先声明函数和原型一样,可以是extern 或者是_declspec(dllimport) 这种效率更高一点。

2. 把DLL 中生成的引入库.lib 复制到当前执行的文件夹下,然后再工程->Setting-> Link->Object/Library modules: 里面再添加引入库。

3. 可以生成文件但是执行不了,这时候要把DLL 也要复制进来。

4. 运行成功。

还可以使用图形化查看工具:Depends 

为了更好的实现,可以定义一个dill.h的头文件,然后在头文件中进行一个宏定义把这个宏定义为_declspec(dllexport),再包含这个头文件。

可以导出一个C++的类,在Class _declspec(dllexport))类名

也可以只导出类中的函数,在该函数返回值和函数名之间加上。必须注意一点,这些导出的函数可以被程序的外界访问,public,否则就算能被导出也不能被程序访问。

希望动态链接库文件在编译的时候,导出函数的名称不要发生改变,为了实现这一目的,在定义导出函数时,需要加上限定符,“extern C,C一定要大写。但是这还不够,因为调用约定,所以要加上 _stdcall  标准调用约定,也就是pascal调用约定。 还有一种方法是模块定义(DEF)文件。创建一个文件后缀名为.def,添加如下语句:

LIBRARY +动态链接库的名称

EXPORTS

函数名称

显示加载(动态加载)动态链接库:

1. 先把DLL 复制过来。不需要引入库和导出函数的声明。

2. 用到函数 返回DLL的句柄 LoadLibraryDLL 名称);

3. 要获得动态链接库中导出函数的地址,要通过调用GetProcAddress()

函数来实现。该函数用来获取DLL导出函数的地址,

GetProcAddress(句柄,指定DLL导出函数的名称或者函数的序号)

   动态加载动态链接库的好处是:当有很多DLL要加载,但是是在一定的情况时候才用到一些DLL,如果采用隐式加载DLL,直接全部加载进去,这样会增大内存消耗和浪费资源,在需要的时候加载进去更好,

注意点:当DLL中的导出函数是采用了标准的约定时候,那么在调用时候,也应该采用同样的约定访问相应的函数。就是在定义函数指针的时候指针前面加上约定。如果是根据序列号来访问,那么要用到一个宏MAKEINTRESOURCE(序列号)把函数序列号转换为函数的名字字符串。

DLLMain 函数 :在编写时候可以提供也可以不写,系统会自动调用。如果提供了函数,最好也不要太复杂,

动态加载的时候如果不用了,要用FreeLibrary(句柄)来释放对DLL引用的计数。