很久以前自己总结的,都是些基础性的东西。
目录
2.2.4 可以使用depends工具验证动态库导出函数的名字... 2
1 动态库简述
动态库是可以导出一组变量,C++类以及函数的可执行模块。
但导出变量打破了封装性,增加了维护的难度
导出c++类,动态库的用户必须使用与编译动态库相同的工具包,至少要有相同的编译器。
因此不提倡在动态库中导出变量与导出c++类。
2 构建动态库的步骤
说明:
这里有依次执行的三个步骤,有时候第二以及第三步骤不是必需的,但它们提供了更好的保障,何况这些步骤操作起来非常简单以及快速,养成一个良好的习惯有何不好呢。
2.1 步骤一,新建工程
2.1.1 步骤描述
使用vs2008或类似的VS/VC工具包,新建一个动态库工程,选择“Win32”方式,然后对它的子选项,无论是选择“win32 console application”还是选择”win32 project”,其结果都是一样的。然后还有子子项,“empty”或“exported”,选择后者。
前者创建的工程是一个完全空的工程,后者会创建一个已经输出了一个变量,一个C++类以及一个函数,并且定义了“MainDll”入口函数的工程,用户只需要在此基础上添加想要输出的内容,如果有必要还可以删掉默认输出的变量,c++类与函数。
2.1.2 动态库导出以及导入的一些原理
动态库导出内容依靠的是:
方法1:在所导出内容的声明处,添加__declspec(dllexport)
方法2:使用def文件,在EXPORTS项中,显示说明需要被导出的内容的名字
至于用户可执行文件在动态链接时导入,使用的是__declspec(dllimport),但这不是必需的,它只是能提高代码的执行效率。
2.2 步骤二,给导出内容添加修饰符
2.2.1 步骤描述
在导出内容的声明前,添加extern “C”
例如,原来的导出函数的声明如下,
WIN32PROJECTEXPORTED_API int fnWin32ProjectExported(void);
添加后,如下:
extern “C” WIN32PROJECTEXPORTED_API int fnWin32ProjectExported(void);
2.2.2 注意
只应该在C++代码中添加,在C代码中不应该添加,依照上面的步骤创建的工程,肯定是C++的代码,所以需要添加。
2.2.3 需要添加的原因
如果不添加,编译器会改编导出变量和函数的名字,这样可能会引起链接问题。
2.2.4 可以使用depends工具验证动态库导出函数的名字
在没有添加extern “C”和添加后分别编译一次,使用depends工具打开编译出来的动态库,会发现没有添加extern “C”时,编译器确实改编了动态库导出的变量名与函数名。
2.3 步骤三,给工程添加xxx.def文件
2.3.1添加def文件
新建一个文件,命名为xxx.def,并添加到工程中
2.3.2 编辑该文件内容如下
LIBRARY "FTPE" // 将FTPE改为动态库的名字(不包括后缀名)
EXPORTS
WSPStartup @1 // 将这些导出函数的名字替换成需要导出的函数名
InstallSPI @2
UninstallSPI @3
2.3.3 该def文件的作用
动态库是给用户使用的,我们不能够确保用户的可执行文件也是使用微软的VS/VC工具包编译生成的,当用户的可执行文件链接到我们的动态库时,如果使用的工具包不同,并且如果没有该def,就可能有链接问题。该def文件确保动态库导出的函数名字是def文件中所定义的。