一、Win32 DLL的创建和使用
     1、从DLL中导出函数
          _declspec(dllexport) int add(int a,int b)
          {
             return a+b;
          }
          _declspec(dllexport) int subtract(int a,int b)
          {
            return a-b;
          }
         
二、隐式加载DLL
     选择【Project\Settings】菜单打开工程设置对话框,选择link选项卡,在"Object/library modules"选项编辑诓中输入dll1.lib
     1、利用extern声明外部函数
          extern int add(int a,int b);
          extern int subtract(int a,int b);
     2、利用_declspec(dllimport)声明外部函数
          _declspec(dllimport) int add(int a,int b);
          _declspec(dllimport) int subtract(int a,int b);
          注意:这样导出的一般放在.h文件中。
     3、利用宏导出DLL
        在.h文件中(Dll1.h)
          #ifdef DLL1_API
          #else
          #define DLL1_API _declspec(dllimport)
          #endif
         
          DLL1_API int add(int a,int b);
          DLL1_API int subtract(int a,int b);
         
        在.cpp文件中
          #define DLL1_API _declspec(dllexport)
          #include "Dll1.h"
          int add(int a,int b)
          {
             return a+b;
          }
          int subtract(int a,int b)
          {
            return a-b;
          }         
     4、从DLL中导出C++类
        在.h文件中(Dll1.h)
          #ifdef DLL1_API
          #else
          #define DLL1_API _declspec(dllimport)
          #endif
         
          class DLL1_API Point
          {
             public:
                void output(int x,int y);
          } 
         
        在.cpp文件中
          #define DLL1_API _declspec(dllexport)
          #include "Dll1.h"
         
          void Point::output(int x,int y)
          {
             HWND hwnd=GetForegroundWindow();          //返回调用者进程当前正在使用的那个窗口的句柄。
             HDC hdc=GetDC(hwnd);                      //获取DC
             char buf[20];
             memset(buf,0,20);
             sprintf(buf,"x=%d,y=%d",x,y);    
             TextOut(hdc,0,0,buf,strlen(buf));         //输出坐标
             ReleaseDC(hwnd,hdc);                      //释放DC
          }          
         
       在客户端使用
          Point pt;
          pt.output(5,3);
         
     5、只导出类的某个方法
        在.h文件中(Dll1.h)
          #ifdef DLL1_API
          #else
          #define DLL1_API _declspec(dllimport)
          #endif
         
          class  Point
          {
             public:
                void DLL1_API output(int x,int y);
                void test();
          }   
        在.cpp文件中
          #define DLL1_API _declspec(dllexport)
          #include "Dll1.h"
         
          void Point::output(int x,int y)
          {
             HWND hwnd=GetForegroundWindow();          //返回调用者进程当前正在使用的那个窗口的句柄。
             HDC hdc=GetDC(hwnd);                     //获取DC
             char buf[20];
             memset(buf,0,20);
             sprintf(buf,"x=%d,y=%d",x,y);    
             TextOut(hdc,0,0,buf,strlen(buf));         //输出坐标
             ReleaseDC(hwnd,hdc);                      //释放DC
          } 
          void Point::test()
          {
          }
         
三、解决名字改编问题
     1、解决C++和C语言之间的命名改编
     希望动态链接库文件在编译时,导出函数的名称不要发生改变。为了实现这一目的,在定义导出函数时,需要加上限定符:extern "C"
     注意双引号中的"C"字母一定要大写。    
        在.h文件中(Dll1.h)
          #ifdef DLL1_API
          #else
          #define DLL1_API extern "C" _declspec(dllimport)
          #endif
         
          DLL1_API int add(int a,int b);
          DLL1_API int subtract(int a,int b);
         
        在.cpp文件中
          #define DLL1_API extern "C"  _declspec(dllexport)
          #include "Dll1.h"
          int add(int a,int b)
          {
             return a+b;
          }
          int subtract(int a,int b)
          {
            return a-b;
          }         
     利用限定符:extern "C"可以解决C++和C语言之间相互调用时函数命名的问题。但是这种方法有一个缺陷,就是不能用于导出一个类的
     成员函数,只能用于导出全局函数这种情况。
     2、通用的解决语言之间命名改编
          通过一个称为模块定义文件(DEF)的方式来解决名字改编
          .cpp文件中函数
          int add(int a,int b)
          {
             return a+b;
          }
          int subtract(int a,int b)
          {
            return a-b;
          }  
          然后建立一个.def的文件,选择【Project\Add To Project\Files...】菜单项,然后弹出"Insert Files into Project" 将.def
          文件加入到工程中。其中.def文件中添加如下代码
          LIBRARY Dll2
         
          EXPORTS
          add
          subtract
         
          当连接器在链接时,会分析DEF文件,当发现EXPORTS语句下面的add和subtract这两个符号名,并且他们与源文件中定义的add和
          subtract函数的名字是一样的时候,它就会以add和subtract这两个符号名导出相应的函数。如果将要导出的符号名和源文件中
          定义的函数名不一样,则可以安装下述语法指定导出函数:
          entryname=internalname
          其中等号左边的entryname项是导出的符号名,右边的internalname项是DLL中将要导出的函数的名字。
         
四、显式加载dll            
          HINSTANCE hInst;
          hInst=LoadLibrary("Dll2.dll");                    //动态加载DLL
          typedef int (*ADDPROC)(int a,int b);              //定义函数指针类型
          ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"add"); //获取DLL的导出函数
          if(!Add)
          {
             MessageBox("获取函数地址失败!");
             return;
          }
          CString str;
          str.format("5+3=%d",Add(5,3));
          MessageBox(str);
         
     1、调用约定
          int _stdcall add(int a,int b)
          {
             return a+b;
          }
          int _stdcall subtract(int a,int b)
          {
            return a-b;
          }
          //客户端调用
          HINSTANCE hInst;
          hInst=LoadLibrary("Dll2.dll");                    //动态加载DLL
          typedef int (_stdcall *ADDPROC)(int a,int b);     //定义函数指针类型
          ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"add"); //获取DLL的导出函数
          if(!Add)
          {
             MessageBox("获取函数地址失败!");
             return;
          }
          CString str;
          str.format("5+3=%d",Add(5,3));
          MessageBox(str);
         
          当DLL中导出函数采用的是标准调用约定时,访问该DLL的客户端程序也应采用该约定类型来访问相应的导出函数。
         
     2、根据序号访问DLL中的导出函数
          HINSTANCE hInst;
          hInst=LoadLibrary("Dll2.dll");                    //动态加载DLL
          typedef int (*ADDPROC)(int a,int b);              //定义函数指针类型
          ADDPROC Add=(ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1)); //获取DLL的导出函数
          if(!Add)
          {
             MessageBox("获取函数地址失败!");
             return;
          }
          CString str;
          str.format("5+3=%d",Add(5,3));
          MessageBox(str);