1、lib.h
1 #ifndef LIB_H
2 #define LIB_H
3
4 #include <windows.h>
5 #include <iostream>
6
7 using namespace std;
8
9 extern "C" int __declspec(dllexport)add(int,int);
10 extern "C" int __declspec(dllexport)sub(int,int);
11
12 //int add(int,int);
13 //int sub(int,int);
14
15 #endif
2、lib.cpp
1 #include "lib.h" 2 3 /*BOOL APIENTRY DllMain(HANDLE hModule, 4 DWORD ul_reason_for_call, 5 LPVOID lpReserved){ 6 switch(ul_reason_for_call){ 7 case DLL_PROCESS_ATTACH: 8 case DLL_THREAD_ATTACH: 9 case DLL_THREAD_DETACH: 10 case DLL_PROCESS_DETACH: 11 break; 12 } 13 return TRUE; 14 }*/ 15 16 int add(int x, int y) 17 { 18 return x + y; 19 } 20 int sub(int x, int y) 21 { 22 return x - y; 23 } 24
3、main.cpp
1 #include "lib.h" 2 3 int main(){ 4 //DLL句柄声明 5 //HINSTANCE hDll; 6 HMODULE hDll; 7 8 //加载DLL,返回句柄: 9 //HMODULE WINAPI LoadLibrary( _In_ LPCTSTR lpFileName); 10 //hDll=LoadLibrary(_T("lib.dll")); 11 hDll=LoadLibrary(TEXT("lib.dll"));//hDll=LoadLibrary("lib.dll"); 12 if(hDll==NULL) 13 cout << "dll加载失败!" << endl; 14 cout << "dll加载成功!" << endl; 15 cout << "dll句柄:" << hDll <<endl; 16 17 //定义与add函数接受参数类型和返回值均相同的函数指针类型 18 typedef int(*lpAddFun)(int,int); 19 typedef int(*lpSubFun)(int,int); 20 21 lpAddFun addFun; 22 lpSubFun subFun; 23 24 // 25 //GetProcAddress函数原型: 26 //FARPROC GetProcAddress( 27 //HMODULE hModule, // DLL模块句柄 28 //LPCSTR lpProcName); // 函数名 29 LPCSTR add="add"; 30 LPCSTR sub="sub"; 31 int *numFun; 32 33 if(hDll!=NULL){ 34 addFun=(lpAddFun)GetProcAddress(hDll,add); 35 cout << "addFun :" << addFun << endl; 36 subFun=(lpSubFun)GetProcAddress(hDll,sub); 37 cout << "subFun :" << subFun << endl; 38 numFun=(int *)GetProcAddress(hDll,"num"); 39 cout << "numFun1:" << numFun << endl; 40 if(addFun!=NULL){ 41 int result=addFun(3,2); 42 cout << "3+2=" << result << endl; 43 } 44 if(subFun!=NULL){ 45 int result=subFun(3,2); 46 cout << "3-2=" << result << endl; 47 } 48 if(numFun!=NULL){ 49 cout << "numFun2:"<< numFun <<endl;//没有num函数,就返回NULL 50 } 51 FreeLibrary(hDll);//释放DLL 52 cout << "dll卸载成功!"; 53 } 54 return 0; 55 }
4、编译lib.cpp为dll
cl /LD lib.cpp
生成lib.dll,同时还有lib.exp、lib.lib
5、编译main.cpp为main.exe
cl main.cpp
6、DLL中导出函数的声明有两种方式:
6.1、一种方式为例子中给出的:
在函数声明中加上__declspec(dllexport)
6.2、另外一种方式是采用模块定义(.def) 文件声明
.def文件为链接器,提供了有关被链接程序的导出、属性及其他方面的信息。
代码中lib.cpp中注释部分演示了怎样同.def文件,
将函数add声明为DLL导出 函数(需在dllTest工程中添加lib.def文件)
lib.def : 导出DLL函数
LIBRARY libdll
EXPORTS
add @ 1
.def文件的规则为:
(1)LIBRARY语句说明.def文件相应的DLL;
(2)EXPORTS语句后列出要导出函数的名称。可以在.def文件中
的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调
用时,这个序号将发挥其作用);
(3).def 文件中的注释由每个注释行开始处的分号 (;) 指定,
且注释不能与语句共享一行。
由此可以看出,例子中lib.def文件的含义为生成名为“libdll”
的动态链接库,导出其中的add函数,并指定add函数的序号为1。
7、当使用第一种声明导出函数函数时,将"C"改为C++,
则main.cpp不能成功调用到lib.dll中的各个函数。