标签:
DLL开发总结
一概论
DLL(Dynamic Linkable Library),你可以简单的把DLL看成一种仓库,它提供给你一些可以直接拿来用的变量,函数。
静态库和动态库都是共享代码的方式,它们的区别请参见我的上一篇博文。
DLL的编制与具体的变成语言及编译器无关
只要遵循约定的DLL接口规范和调用方式,用各种语言编写的DLL都可以
相互调用,譬如Windows提供的系统DLL,在任何开发环境中都能被调用,不在乎其实VisualBasics、Visual C++还是Delphi。
VC动态链接库的分类
VisualC++支持三种DLL,它们分别是Non-MFCDLL(非MFC动态库)、MFC
Regular DLL(MFC规则的DLL)、MFCExtension DLL(MFC扩展DLL)。
非MFC动态库不采用MFC类库结构,其导出函数为标准的C接口,能被非MFC编写的应用程序所调用;MFC规则DLL包含一个继承自CWinApp的类,但其无消息循环;MFC扩展DLL采用MFC的动态链接版本创建,她们只能被用MFC类库所编写程序所调用。
二导出函数
DLL中导出函数的声明有两种方式:一种是在函数声明中加上__declspec(dllexport),另外一种是采用模块定义(.def)文件声明,.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。
①extern “C” int __declspec(dllexport) add(int x, int y);怎样使用可以参见上一篇博客——静态库与动态库的区别。
②LIBRARY dllTest
EXPORTS
add @1
.def文件的规则为:
①LIBRARY语句说明.def文件相应的DLL;
②EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数后面加@n,表示要导出函数的序号为n
③.def文件中的注释由每个注释行开始处的分号指定,且注释不能与语句同行。
使用.def文件在使用时,可以这样
hDll = LoadLibrary(“dllTest.dll”);
if(hDll!= NULL)
addFun = (lpAddFun)GetProcAddress(hDll,MAKEINTRESOURCE(1));
FreeLibrary(hDll);
其中1为导出函数的序号。
三导出变量
DLL定义的全局变量可以被调用进程访问;DLL也可以访问调用进程的全局数据,我们来看看在应用工程中引用DLL中变量的例子。
Lib.h
#ifndef LIB_H #define LIB_H extern intdllGlobalVar; extern"C" int GetGlobalVar(); #endif
lib.cpp
#include"lib.h" #include<windows.h> intdllGlobalVar; BOOL APIENTRYDllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: dllGlobalVar = 100; break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
.def文件为
LIBRARY dllTest EXPORTS dllGlobalVarDATA
使用方法:
#include"stdafx.h" #include<windows.h> #include<stdio.h> #pragmacomment(lib,"dllTest.lib") extern intdllGlobalVar; int main(intargc, char* argv[]) { printf("%d ",GetGlobalVar()); *(int *)dllGlobalVar = 1; //特别要注意的是这种方法导出的并不是变量本身,而是DLL中导出变量的指针,应用程序必 //须通过强制指针转换来使用 printf("%d ",GetGlobalVar()); return 0; }
如果执行这样的赋值操作:
dllGlobalVar= 1;
其结果是dllGlobalVar指针的内容发生变化,程序中以后再也引用不到这个变量了。所以在应用工程中引用DLL中全局变量的一个更好的方法是:
externint _declspec(dllimport) dllGlobalVar;//用_declspec(dllimport)导入
通过_declspec(dllimport)方式导入的就是DLL中全局变量本身而不再是地址了,所以建议在一切可能的情况下都使用这种方式。
四DLL导出类
point.h
#ifndefPOINT_H #definePOINT_H #ifdefDLL_FILE class_declspec(dllexport) point //导出类point #else class_declspec(dllimport) point //导入类point #endif { public: float y; float x; point(); point(float x_coordinate,floaty_coordinate ); }; #endif
point.cpp
#ifndefDLL_FILE #defineDLL_FILE #endif #include"point.h" ////////////////////////////////////////////////////////////////////// //Construction/Destruction ////////////////////////////////////////////////////////////////////// point::point() { } point::point(floatx_coordinate,float y_coordinate) { x = x_coordinate; y = y_coordinate; }
circle.h
#ifndefCIRCLE_H #defineCIRCLE_H #include"point.h" #ifdefDLL_FILE class_declspec(dllexport) circle //导出类circle #else class_declspec(dllimport) circle //导入类circle #endif { public: void SetCentre(const point¢rePoint); void SetRadius(float r); float GetGirth(); float GetArea(); circle(); private: float radius; point centre; }; <p>#endif</p>
circle.cpp
#ifndefDLL_FILE #defineDLL_FILE #endif #include"circle.h" #definePI 3.1415926 circle::circle() { centre = point(0,0); radius = 0; } floatcircle::GetArea() { return PI*radius*radius; } floatcircle::GetGirth() { return 2*PI*radius; } voidcircle::SetCentre(const point ¢rePoint) { centre = centrePoint; } voidcircle::SetRadius(float r) { radius = r; }
调用:
dllCall.cpp
#include"stdafx.h" #include<windows.h> #include"..\circle.h" #pragmacomment(lib,"dllTest.lib"); intmain(int argc, char* argv[]) { circle c; point p(2.0,2.0); c.SetCentre(p); c.SetRadius(1.0); printf("area:%fgirth:%f",c.GetArea(),c.GetGirth()); return 0; }
从上述源代码可以看出,由于在DLL的类实现代码中定义了宏DLL_FILE,故在DLL的实现中所包含的类声明实际上为
Class_declspec(dllexport) point { ……. };
和
class_declspec(dllexport) circle { ………….. };
而在应用工程dllCall.cpp中没有定义DLL_FILE,故其包含point.h和circle.h后引入的类声明为:
Class_declspec(dllimport) point { ………. };
和
class_declspec(dllimport) circle { ………. };
我们往往通过在类的声明头文件中用一个宏来决定使其编译为class_declspec(dllexport) class_name还是class_declspec(dllimport) class_name版本,这样就不需要两个头文件。
讨论静态库和动态库区别的博客链接
http://blog.csdn.net/lqlblog/article/details/48086569
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/lqlblog/article/details/48105883