DLL的编写与使用(C++)
DLL可以理解为具有一定功能的可以嵌入到可执行程序中的程序片段。
与lib文件一样,DLL在VS中可以有两种编译方式:C编译、C++编译。个人感觉动态加载DLL文件,使用DLL内部函数的时候倒都是一样的。
一、C编译方式。
A:dll的生成
1 //File of "sub.h" 2 #ifndef SUB_H 3 #define SUB_H 4 extern "C" int __declspec(dllexport)sub(int x, int y); 5 #endif 6 7 //File of "sub.cpp" 8 #include"sub.h" 9 int sub(int x, int y) 10 { 11 return x-y; 12 }
B:dll的使用(动态调用)
1 #include<Windows.h> 2 typedef int(*lpAddFun)(int, int); 3 4 int main() 5 { 6 HINSTANCE hDll; 7 lpAddFun subFun; 8 9 hDll = LoadLibrary(TEXT("..\\DLL\\DLL_study2.dll")); 10 subFun = (lpAddFun)GetProcAddress(hDll,"sub"/*"?sub@@YAHHH@Z"*/); 11 int x = subFun(3,8); 12 FreeLibrary(hDll); 13 14 return 0; 15 }
注意问题:如果在生成的时候"sub.h"不加extern "C"那么按照C++的方式编译,编译完成后函数的名字按照C++的方式改写(mangled name)。当动态调用的时候语句 subFun = (lpAddFun)GetProcAddress(hDll,"sub"/*"?sub@@YAHHH@Z"*/); 按照sub就找不到sub函数了。但是按照注释的名字可以。(C++编译的时候将sub函数的名字改成那样了。)也就是说,只要GetProcAddress函数第二个参数(要找的函数名字)与编译生成后的名字一致就行了(不管DLL是什么方式编译成功的)。(很诡异的事情是:当生成了dll后用dependency查看的时候,如果release版本在生成的地方看怎么都是C编译的方式,但是把dll复制到其他地方就该是什么方式就什么方式了。可能是dependency有记忆功能,我前后试过几次他看是一样的文件名就没更改了。)
二、生成DLL的时候使用.def文件。
这样做的时候"sub.h"文件就不用extern “C" 和 __declspec(dllexport)这些东西了。
LIBRARY
EXPORTS
sub @ 1
函数名字就规定为sub了。编译方式貌似是C的(不敢确定dependency 的结果啊!)不过不管是哪种方式函数名字肯定是确定了的啦。