您的位置:首页 > 其它

DLL(Dynamic Link Library),动态链接库。

2011-11-29 16:10 369 查看
DLL(Dynamic Link Library),动态链接库。

1.关于__declspec(dllimport)和__declspec(dllexport)

在一个DLL的编写过程中,如果要使一个变量、一个函数或一个类能够被外部程序调用,在函数声明上加上__declspec(dllimport)关键字。

例:

引出一个变量:

__declspec(dllexport) int iEx;

引出一个函数:

__declspec(dllexport) int fnEx( int i );

引出一个类:

class __declspec(dllexport) CClassEx

{……};

在外部程序引用DLL时,如果采用隐式调用的方法(关于隐式调用稍后讨论),需要 包含DLL文件相关的头文件,这个头文件用__declspec(dllimport)关键字指出了DLL导出的内容(实际上就是把原来的__declspec(dllexport)全部替换为__declspec(dllimport))。

例:

引入一个变量:

__declspec(dllimport) int iEx;

引入一个函数:

__declspec(dllimport) int fnEx( int i );

引入一个类:

class __declspec(dllimport) CClassEx

{……};

为了提高程序可读性,可以定义如下宏:

#define DllImport __declspec(dllimport)

#define DllExport __declspec(dllexport)

以便使用。

实际上一般定义如下宏:

#ifdef MYDLL_EXPORTS

#define MYDLL_API
__declspec(dllexport)

#else

#define MYDLL_API
__declspec(dllimport)

#endif

这样,在源程序的实现文件中先定义MYDLL_EXPORTS,再包含这个头文件;在外程序内,可以直接包含这个头文件。这种方法可以实现一个文件多种用途。

2.隐式调用和显式调用

隐式调用是最常用的一种调用方法。它需要原DLL文件、原头文件和库文件组成。在程序内要包含这个头文件,并加入库文件一同编译。在程序启动时会把所有隐式调用的DLL文件加载到内存。

如果想在使用的时候才把DLL文件加入到内存的话,可以使用显式调用。显式调用只需要原DLL文件即可,但是使用时必须对知道这个DLL有哪些导出的符号。可以在VS的命令行方式下输入“depends”命令来查看DLL信息。

示例:

隐式调用:

#include
"..\DllTest\DllTest.h"

……

void CallDll(
void )

{

wchar_t wszBuf[ 32 ];

wsprintf( wszBuf, TEXT( "%d" ), fnDllTest( 9 ) );//fnDllTest是DLL文件导出的方法

wprintf( wszBuf );

}

显式调用:

void CallDll(
void )

{

typedef
int (*ADDPROC)(
int i );

ADDPROC Fn;

HINSTANCE hInst = LoadLibrary( L"DllTest.dll" );

if ( NULL == hInst )

{

wprintf( L"Failed on load DLL." );

return;

}

Fn = ( ADDPROC )GetProcAddress( hInst, "fnDllTest" );

//如果导出时使用的是_stdcall,
那么这里我们也应该使用(_stdcall ADDPROC)

if( !Fn )

wprintf( L"Failed on get Process Address." );

else

{

int i;

i = Fn( 9 );

wchar_t wszBuf[ 32 ];

wsprintf( wszBuf, L"%d", i );

wprintf( wszBuf );

}

FreeLibrary(hInst);//释放DLL

/*

* ADDRPROC Add = (ADDPROC)GetProcAddress(hInst, "add");

* 第而个参数也可以使用序号:

* MAKEINTRESOURCE(1)代替函数名.

*/

}

3.注意事项

如果使用C++编程,那么在程序编译的时候会为变量名等符号重命为诸如“?fnDllTest@QAEAAV0”之类的形式,为显式调用带来了不便。针对这个问题,我们可以为要导出的符号加上“extern
“C””修饰符,就可以保持原有名称。但是导出的类名仍然是重命名后的名称,要再研究研究。

最新发现(05-Nov-2007):用extern "C" struct __declspec(dllexport) classname即可按C格式导出类名。

如果你使用MFC生成MFC DLL那么只要做如下定义就可以了class AFX_EXT_CLASS yourClass。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: