DLL总结

来源:互联网 发布:asp企业网站源码下载 编辑:程序博客网 时间:2024/05/26 23:00

转载:点击打开链接

一、在dll中定义输出函数

        总体有两种方法,一种是添加def定义文件,在def文件中定义要输出的函数;另一种是在源代码中待输出的函数前加上__declspec(dllexport)关键字。

1、添加def定义文件

dll_def.cpp文件:

<span style="font-family:KaiTi_GB2312;font-size:14px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:14px;">#include <objbase.h>#include <iostream>void FuncInDll(){std::cout<<"FuncInDll is called!"<<std::endl;}BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void *lpReserved){HANDLE g_hModule;switch(dwReason){case DLL_PROCESS_ATTACH:hModule;break;case DLL_PROCESS_DETACH:g_hModule = NULL;break;default:break;}return TRUE;}</span></span></span>

dll_def.def文件
<span style="font-family:KaiTi_GB2312;font-size:14px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:14px;">LIBRARYdll_def.dllDESCRIPTION'write by ycg'EXPORTSFuncInDll @1 PRIVATE</span></span></span>

用如下命令编译

cl /c dll_def.cpp

link /dll dll_def.obj /def:dll_def.def

再用dunpbin -exports dll_def.dll查看库的信息,可以发现该dll导出了函数FuncInDll。


2、__declspec(dllexport)

为每个dll写def显得繁杂,更多的是使用__declspec(dllexport)

Dll写法同上,去掉def文件,并在每个要输出的函数前面加上声明__declspec(dllexport)

<span style="font-family:KaiTi_GB2312;font-size:14px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:14px;">__declspec(dllexport) void FuncInDll()</span></span></span>

然后编译链接

cl /c dll_withlib.cpp

link /dll dll_withlib.obj

这里要注意,C++编译器基于函数重载的考虑,会更改函数名,可以使用extern "C"指令来命令C++编译器以C编译器的方式来命名该函数。

<span style="font-family:KaiTi_GB2312;font-size:14px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:14px;">extern "C" _declspec(dllexport) void FuncInDll()</span></span></span>

二、dll的调用方式

        dll可通过隐式调用和显示调用来加载

1、显示调用

      先调用LoadLibrary将dll库加载进程序

      通过GetProcAddress函数获取库中函数的地址

      通过函数指针调用


<span style="font-family:KaiTi_GB2312;font-size:14px;"><span style="font-family:KaiTi_GB2312;font-size:14px;">#include <windows.h>#include <iostream>int main(){//定义一个函数指针typedef void(* DLLWITHLIB)(void);//定义一个函数指针变量DLLWITHLIB pfFuncInDll = NULL;//加载DLLHINSTANCE hinst = ::LoadLibrary("dll_def.dll");if(NULL != hinst){std::cout<<"dll loaded"<<std::endl;}//找到dll里函数的地址pfFuncInDll = (DLLWITHLIB)GetProcAddress(hinst, "FuncInDll");//调用if(NULL != pfFuncInDll){(*pfFuncInDll)();}getchar();return 0;}</span></span>

2、隐式调用
      dll包含两个文件,cpp文件和头文件

dll_object.h文件
<span style="font-family:KaiTi_GB2312;font-size:14px;">#ifdef DLL_OBJECT_EXPORTS#define DLL_OBJECT_API __declspec(dllexport)#else#define DLL_OBJECT_API __declspec(dllimport)#endif//导出函数DLL_OBJECT_API void FuncInDll(void);//导出全局变量extern DLL_OBJECT_API int g_nDll;//导出类class DLL_OBJECT_API CDll_Object{public:CDll_Object(void);void show(void);};</span>

dll_object.cpp文件
<span style="font-family:KaiTi_GB2312;font-size:14px;">#define DLL_OBJECT_EXPORTS#include <objbase.h>#include <iostream>#include "dll_object.h"DLL_OBJECT_API void FuncInDll(void){std::cout<<"FuncInDll is called!"<<std::endl;}DLL_OBJECT_API int g_nDll = 9;CDll_Object::CDll_Object(){std::cout<<"init of CDll_Object"<<std::endl;}void CDll_Object::show(){std::cout<<"function show in class CDll_Object"<<std::endl;}BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved){HINSTANCE g_hModule;switch(dwReason){case DLL_PROCESS_ATTACH:g_hModule = (HINSTANCE)hModule;break;case DLL_PROCESS_DETACH:g_hModule = NULL;break;default:break;}return TRUE;}</span>

调用时,客户端引入头文件,并在链接时指明dll对应的lib文件位置和名称,然后如同调用api函数库中的函数一样调用dll中的函数
client.cpp
<span style="font-family:KaiTi_GB2312;font-size:14px;">#include "dll_object.h"#include <iostream>using namespace std;#pragma comment(lib, "dll_object.lib")int main(){cout<<"call dll"<<endl;cout<<"call function in dll"<<endl;//调用dll中的函数FuncInDll();//dll中的全局变量cout<<"global var in dll g_nDll = "<<g_nDll<<endl;//调用dll中的类CDll_Object obj;obj.show();return 0;}</span>


三、在一个dll中调用另一个dll
dll1.h
<span style="font-family:KaiTi_GB2312;font-size:14px;">#ifdef DLL_DLL1_EXPORTS#define DLL_DLL1_API __declspec(dllexport)#else#define DLL_DLL1_API __declspec(dllimport)#endifDLL_DLL1_API void FuncInDll1(void);DLL_DLL1_API void FuncInDll1(int);</span>
dll1.cpp
<span style="font-family:KaiTi_GB2312;font-size:14px;">#define DLL_DLL1_EXPORTS#include <objbase.h>#include <iostream>#include "dll1.h"DLL_DLL1_API void FuncInDll1(void){std::cout<<"FuncInDll1 is called!"<<std::endl;}DLL_DLL1_API void FuncInDll1(int a){std::cout<<"FuncInDll1 is called! input param = "<<a<<std::endl;}BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved){HINSTANCE g_hModule;switch(dwReason){case DLL_PROCESS_ATTACH:g_hModule = (HINSTANCE)hModule;break;case DLL_PROCESS_DETACH:g_hModule = NULL;break;default:break;}return TRUE;}</span>

dll2.h
<span style="font-family:KaiTi_GB2312;font-size:14px;">#include "dll1.h"#ifdef DLL_DLL2_EXPORTS#define DLL_DLL2_API __declspec(dllexport)#else#define DLL_DLL2_API __declspec(dllimport)#endifDLL_DLL2_API void FuncInDll2(void);DLL_DLL2_API void FuncInDll2(int);</span>

dll2.cpp
<span style="font-family:KaiTi_GB2312;font-size:14px;">#define DLL_DLL2_EXPORTS#include <objbase.h>#include <iostream>#include "dll2.h"#pragma comment(lib, "dll1.lib")//在DLL2中调用DLL1中的函数DLL_DLL2_API void FuncInDll2(void){FuncInDll1();std::cout<<"FuncInDll2 is called!"<<std::endl;}DLL_DLL2_API void FuncInDll2(int a){FuncInDll1(10);std::cout<<"FuncInDll2 is called! input param = "<<a<<std::endl;}BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved){HINSTANCE g_hModule;switch(dwReason){case DLL_PROCESS_ATTACH:g_hModule = (HINSTANCE)hModule;break;case DLL_PROCESS_DETACH:g_hModule = NULL;break;default:break;}return TRUE;}</span>



0 0
原创粉丝点击