DLL学习
创建工程:win32->dll
静态库:lib在编译连接时copy进去后生成exe文件
动态库使用:
- 引入库(dll文件导出函数和变量符号名)(编译连接时使用,不复制dll文件里的函数和变量)
- dll文件(实际函数和数据)(程序运行时加载相应的函数)
隐式链接:
查看动态链接库中的导出函数
dumpbin工具
dumpbin –exports *.dll(大小写无关)
__declspec(dllexport) int fun(){
}
为了支持C++重载(同名) 名字粉碎所以名字乱
- extern int myadd(int a,int b);
- __declspec(dllimport) int myadd(int a,int b);
dll工程会同时产生dll文件和lib引入库
link->lib引入库
查看可执行文件的输入信息
dumpbin –imports *.exe(大小写无关)
testdll.exe 与dll1.dll同一个目录下,上面是exe文件的依赖库,下面是依赖库的导出函数
提供头文件给用户使用。
.h
__declspec(dllimport) int fun1(int a,int b); __declspec(dllimport) int fun2(int a,int b); __declspec(dllimport) int fun3(int a,int b); ...... ......
包含以上头文件使用即可
//导出类 class DLL1_API Cdll1 { public: Cdll1(void); // TODO: 在此添加您的方法。 }; //仅仅导出类中的某些函数 class Cdll1 { public: Cdll1(void); // TODO: 在此添加您的方法。 DLL1_API void fun();//导出该方法 };
虽然类没有导出,但仍然可以构造对象
注意:定义类的方法全部要在cpp文件里实现,否则会出错!包括构造函数!
class Cdll2 { //虽然整个类不是导出的但是,构造函数一定要导出,否则生成对象会链接出错 public: DLL1_API Cdll2(void); // TODO: 在此添加您的方法。 DLL1_API void fun2(); void fun3(); };
#define DLL1_API extern "C" __declspec(dllexport)//导出名字与函数名字一样
DLL1_API int _stdcall fun();//win_api调用约定 DLL1_API int fun();//c++调用约定 //粉碎命名规则不一样!
模块定义文件:
*.def 调用约定不会改变粉碎命名规则!
LIBRARY dll1 EXPORTS //导出函数名字,与cpp文件定义的要导出的同名
cpp中就不需要
DLL1_API int fun();//
动态加载 启动快速,节约内存资源
映射可执行模块到调用进程的地址空间
HMODULE LoadLibrary( LPCTSTR lpFileName // file name of module );
加载dll和exe
LPCTSTR lpFileName 指向dll和exe地址的字符串指针
得到导出函数地址:
FARPROC GetProcAddress( HMODULE hModule, // handle to DLL module LPCSTR lpProcName // function name );
动态加载 一般要有extern "C"
extern "C" DLL1_API int myadd(int a,int b) { return a+b; }
HINSTANCE hinst; hinst=LoadLibrary("dll1.dll"); typedef int (*ADDPROC)(int a,int b); ADDPROC ad=(ADDPROC)GetProcAddress(hinst,"myadd");
// typedef int (_stdcall *ADDPROC)(int a,int b); 调用约定改变时
if (!ad) { printf("没有得到函数地址失败!"); return 0; } int i=ad(4,7); printf("%d\n",i);
否则会报“没有得到函数地址”的错误
此时
dumpbin –imports *.exe
没有dll1.dll的信息
命令行下的复制 ,选择->右键->已经复制成功!
ADDPROC ad=(ADDPROC)GetProcAddress(hinst,MAKEINTRESOURCE(dumpbin ordinal));
DLLMain()函数
BOOL WINAPI DllMain( HINSTANCE hinstDLL, // handle to the DLL module DWORD fdwReason, // reason for calling function LPVOID lpvReserved // reserved );
dll加载时,句柄传递进来可以给其他程序(通过进程间的通信:管道等)使用
主要dll.cpp文件里有DllMain()则,dll被加载时,自动调用DllMain()函数
新建mfc支持的dll
regular dll using shared mfc dll 用户机器上得有mfc dll 才可以运行你的MFC dll(自己的c++类可以导出)
mfc extension dll 导出mfc类
BOOL FreeLibrary( HMODULE hModule // handle to DLL module );