dll技术

dll是windows编程非常常用的技术之一;通过孙鑫教程学习和windows核心编程学习;由浅入深简单总结一下:

隐式链接:

(1)最简单的dll
    在vs环境下,新建dll工程,然后新建对应的“dll1.cpp”;编辑最简单一个函数

//dll1.cpp 
int dllfun(int a,int b)
{
      return a*b;
}
//运行会生成dll1.dll

    新建win32 application 或者mfc,在工程中建立testdll.cpp

//testdll.cpp
   .....
extern int dllfun(int a,int b);  
//(引用之前,需要输入dll文件路径,导入在link->object/library modules 加入 dll1.dll)
//或者是和 #pragma comment(lib,"dll1.lib")
main()
{
      dllfun(1,2);
}

   但是通过在cmd中 运行dumpbin /imports dll1.dll 我们会发现没有函数导出 那么怎么显示函数导出呢?

(2)使用__declspec(dllexport)   

__declspec(dllexport)   表示导出,只要导出还是在dumpbin中可以查看到
改进上面dll1.dll中代码为:
__declspec(dllexport) int dllfun(int a,int b)
{
    return a*b;
}
//运行会生成dll1.dll ,同时多生成dll1.lib

改进 testdll.cpp为:(提前导入dll1.lib和dll1.dll)
__declspec(dllimport)   int dllfun(int a,int b);   (等价于 extern int dllfun(int a,int b); )
.......//其它相同
我们可以通过“dumpbin -imports dllTest.exe” 查看输入信息 ,也可以通过Dependency工具查看exe和dll;

(3)对dll文件,进一步的优化,dll中包含“.h”文件

   在dll 增加“.h”文件;既可以dll自身方便使用,也可以方面外部调用
   改进工程dll1; 新建dll1.h //link->object/library modules 加入 dll1.lib
 

  // dll1.h

#ifdef DLL1_API
#else
#define DLL1_API extern "C" _declspec(dllimport)   
// extern "C" 保证了,编译后在dumpbin查看,函数名称不变;
#endif
  
DLL1_API int _stdcall dllfun(int a,int b);
//dll1.cpp
#define DLL1_API extern "C" _declspec(dllexport)
#include "Dll1.h"
#include <Windows.h>
#include <stdio.h>
............
int dllfun(int a,int b)  
//int __stdcall dllfun(int a,int b) ; 及时使用extern "C" ,dumpbin下函数名称还是变化“dllfun@8”
   {
      return a*b;
   }
............
    在dlltest工程中,testdll.cpp (拷贝"Dll1.h",“dll1.dll”、“dll1.lib”到dlltest工程下)
    #include "Dll1.h"
   .......
   dllfun(1,2);
   ......

(4)dll中导出“类”和“类中的函数”

// dll1.h

#ifdef DLL1_API
#else
#define DLL1_API _declspec(dllimport)//注意不能使用#define DLL1_API extern "C" _declspec(dllimport)
#endif
  
class DLL_API classdll    // 导出整个类
   {
     public:
        void fun();
}
/*
    class classdll    // 导出类中的某个函数
   {
     public:
        DLL_API void fun();
}

*/
//dll1.cpp
#include "dll1.h"
void classdll::fun()
{
    //your code
}
dllTest工程中, dlltest.cpp
#include "dll1.h"
......
   classdll cd;
   cd.fun();
......

动态加载:

(1)保持定义的函数名 不被改变,引入模块定义文件
在dll工程中可以,新建文件,引入“dll2.def”(def为模块定义文件,在此作用是在dll动态加载过程中保持dll函数名称不变;即dumpbin下查看dll输出,没有发生函数名转化)

//dll2.def
LIBRARY DLL2 
EXPORTS     //注意单词拼写
add
   //dll2.cpp
int _stdcall add(int a,int b) //或者int add(int a,int b)
{
return a+b;
}
int _stdcall subtract(int a,int b) //或者int subtract(int a,int b)
{
return a-b;
}
编译生成dll2.dll 通过dumpbin可以看到 导出的函数名没有被改变( 没有发生名字改编


(2)动态加载:(隐士链接初始化,消耗太大)
直接copy “dll2.dll”到该工程下即可 不需要加载link->object.....
dllTest中:

HINSTANCE hInst;
hInst=LoadLibrary("Dll3.dll");
typedef int (/*_stdcall*/ *ADDPROC)(int a,int b);   //函数类型
ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"add");
if(!Add)
{
   MessageBox("获取函数地址失败!");
   return;
}
在测试过程中 动态加载dll时候,本人还未在def文件中导出整个类;对类的导出 不能加 extern "C" ; 在隐士加载dll中,可以通过加载“.h”文件,引起类;动态加载中就如何导出呢?进一步解决中..........

dll入口函数DLLMain():(可选函数)
不要做复杂的操作,做一点内存分配等等

你可能感兴趣的:(dll技术)