Kim_zh

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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 
lib.h

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     
lib.cpp

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 }
main.cpp

 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中的各个函数。

 

 

 

 

posted on 2014-07-06 02:58  Kim.zh  阅读(796)  评论(0编辑  收藏  举报