DLL学习

 

 

创建工程:win32->dll

静态库:lib在编译连接时copy进去后生成exe文件

动态库使用:

  1. 引入库(dll文件导出函数和变量符号名)(编译连接时使用,不复制dll文件里的函数和变量)
  2. dll文件(实际函数和数据)(程序运行时加载相应的函数)

隐式链接:

查看动态链接库中的导出函数

dumpbin工具

dumpbin  –exports  *.dll(大小写无关)

__declspec(dllexport)   int fun(){   

}

 

42_thumb4

为了支持C++重载(同名)       名字粉碎所以名字乱

  1. extern int myadd(int a,int b);
  2. __declspec(dllimport)   int myadd(int a,int b);

dll工程会同时产生dll文件和lib引入库

link->lib引入库

 

43_thumb

 

44_thumb2

 

查看可执行文件的输入信息

dumpbin  –imports  *.exe(大小写无关)

 

45_thumb

46_thumb

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;
}

 

47_thumb

    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);

否则会报“没有得到函数地址”的错误

48_thumb

 

此时

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加载时,句柄传递进来可以给其他程序(通过进程间的通信:管道等)使用

_thumb

主要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
);
posted @ 2013-10-28 18:28  小菜鸟_yang  阅读(628)  评论(0编辑  收藏  举报