标签:
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