2009年8月19日星期三

动态调用DLL中的函数

现有动态链接库DLL_Sample.dll

DLL_Sample.h:
#ifdef TEST_API
# define TEST_API _declspec(dllexport)
#else
# define TEST_API _declspec(dllimport)
#endif

TEST_API
int fuc(int a);
TEST_API
int fuc(int a, int b);
TEST_API
int fuc(int a, int b, int c);

DLL_Sample.cpp:
#define TEST_API
#include
"DLL_Sample.h"

TEST_API
int fuc(int a)
{
return a;
}

TEST_API
int fuc(int a, int b)
{
return a + b;
}

TEST_API
int fuc(int a, int b, int c)
{
return a + b + c;
}


在动态调用dll之前,需要查看一下dll导出的函数名称。
查看编译器的导出名称,可以用VS工具目录下的Dependency Walker,或者在控制台下使用命令:dumpbin /exports DLL_Sample.dll

这里我用dumpbin命令得到下面的信息:

1 0 00011348 ?fuc@@YAHH@Z
2 1 00011352 ?fuc@@YAHHH@Z
3 2 000111DB ?fuc@@YAHHHH@Z


可以看到,重载函数各个版本的名称是不同的,这是因为编译器重新编码了重载函数的名称。
为了方便记忆和使用,我们需要指定重载函数的命名规则,由于导出函数名的唯一性,我们无法将重载函数指定成相同的名称,所以我们采用fuc1、fuc2、fuc3来标识fuc函数的不同版本。
我们用模块定义文件(.def)来定义dll导出。

DLL_Sample.def:

LIBRARY DLL_Sample
EXPORTS
fuc1
=?fuc@@YAHH@Z
fuc2
=?fuc@@YAHHH@Z
fuc3
=?fuc@@YAHHHH@Z

然后写动态调用的示例代码(这里调用了第二个版本的fuc函数):

HINSTANCE hInst
= LoadLibrary("Dll_Sample.dll");
typedef
int (*MyProc)(int a, int b);
MyProc Fuc
= (MyProc)GetProcAddress(hInst, "fuc2");

if (!Fuc)
{
MessageBox (
"Fuc2 is null!");
return;
}

CString str;
str.Format (
"a + b = %d", Fuc(2, 3) );
MessageBox(str);

FreeLibrary (hInst);

结果输出“a + b = 5”

没有评论:

发表评论