使用LoadLibrary函數(shù)調(diào)用DLL中的函數(shù)的方法一般被稱為“顯式”調(diào)用,意義和使用lib的“隱式”調(diào)用相對應(yīng)。
LoadLibrary調(diào)用DLL中的函數(shù)的方法比較簡單,通過GetProcAddress獲得函數(shù)的在DLL的地址就可以訪問了,但DLL中的Class訪問就相對很復(fù)雜了(目前我就發(fā)現(xiàn)這一種顯式調(diào)用方式,哪位有其他方法么?)。一個簡單的情況就是Class的函數(shù)在調(diào)用是,其名稱是什么?還有Class的contructor函數(shù)怎么調(diào)用?下面的代碼將演示下這些問題。
這里是DLL的文件:
DllMain.h
1
#ifndef __DLLMAIN_H__
2
#define __DLLMAIN_H__
3
4
#include <string>
5
6
#define DllExport __declspec(dllexport)
7
8
extern "C" int DllExport Func(int x);
9
10
extern "C" class DllExport CA
11

{
12
public:
13
CA(int x);
14
~CA();
15
16
int Func0();
17
int Func(int x);
18
const std::string& FuncS(int x, const std::string& str) const;
19
protected:
20
int _x;
21
};
22
23
24
#endif
DllMain.cpp
1
#include <iostream>
2
3
#include "DllMain.h"
4
5
int Func(int x)
6

{
7
return x * 10;
8
}
9
10
CA::CA(int x)
11
: _x(x)
12

{
13
std::cout << "contructor" << std::endl;
14
}
15
16
CA::~CA()
17

{
18
std::cout << "destructor" << std::endl;
19
}
20
21
int CA::Func0()
22

{
23
return _x;
24
}
25
26
int CA::Func(int x)
27

{
28
return _x * x;
29
}
30
31
const std::string& CA::FuncS(int x, const std::string &str) const
32

{
33
return str;
34
}
35
這里需要.def文件了,因為Class在DLL中的命名不像函數(shù)命名那么簡單,會被轉(zhuǎn)義的,像CA::Func(int)在DLL的export表中就是
?Func@CA@@QAEHH@Z,具體定義說明可參看《xxx的自我修養(yǎng)》一書。因此,這里需要使用.def文件對函數(shù)進行重命名,下面是DllMain.def文件內(nèi)容:
1
LIBRARY TESTDLL
2
EXPORTS
3
Func = Func
4
CA::CA(int) = ??0CA@@QAE@H@Z
5
CA::~CA = ??1CA@@QAE@XZ
6
CA::Func0 = ?Func0@CA@@QAEHXZ
7
CA::Func(int) = ?Func@CA@@QAEHH@Z
8
;CA::FuncS(int,std::basic_string<char>&) = ?FuncS@CA@@QBEABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HABV23@@Z
9
CA::FuncS = ?FuncS@CA@@QBEABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HABV23@@Z
多說一句,這里.def的編寫很需要Depends(Dependency Walker)工具的支持,其是查看DLL的首選工具啊。。

編譯DLL,用下面代碼進行測試:
LoadLib.cpp
1
#include <iostream>
2
#include <string>
3
4
#include <windows.h>
5
6
//#include "DllMain.h"
7
8
#define DllExport __declspec(dllexport)
9
10
extern "C" int DllExport Func(int x);
11
12
extern "C" class DllExport CA
13

{
14
public:
15
CA(int x);
16
~CA();
17
18
int Func0();
19
int Func(int x);
20
const std::string& FuncS(int x, const std::string& str) const;
21
22
private:
23
int _x;
24
};
25
26
typedef int (*func)(int);
27
typedef void (WINAPI *PCTOR)(int);
28
typedef int (WINAPI *func0)(void);
29
typedef int (WINAPI *funcc)(int);
30
typedef const std::string& (WINAPI *funcs)(int,const std::string&);
31
typedef void (WINAPI *PDTOR)(void);
32
33
int main()
34

{
35
HINSTANCE hdll;
36
hdll = LoadLibraryA(("../DLLTEST/Debug/DLLTEST.dll"));
37
if(hdll != NULL)
38
{
39
func pf = (func)GetProcAddress(hdll, "Func");
40
std::cout << pf(10) << std::endl;
41
CA* a = (CA*)malloc(sizeof(CA));
42
PCTOR pc = (PCTOR)GetProcAddress(hdll, "CA::CA(int)");
43
_asm
{ MOV ECX, a }
44
pc(5);
45
func0 pf0 = (func0)GetProcAddress(hdll, "CA::Func0");
46
_asm
{MOV ECX, a }
47
std::cout << pf0() << std::endl;
48
funcc pfc = (funcc)GetProcAddress(hdll, "CA::Func(int)");
49
_asm
{ MOV ECX, a }
50
std::cout << pfc(10) << std::endl;
51
funcs pfs = (funcs)GetProcAddress(hdll, "CA::FuncS");
52
_asm
{ MOV ECX, a }
53
std::cout << pfs(0, std::string("hello world")) << std::endl;
54
PDTOR pd = (PDTOR)GetProcAddress(hdll, "CA::~CA");
55
_asm
{ MOV ECX, a }
56
pd();
57
free(a);
58
}
59
FreeLibrary(hdll);
60
61
return 0;
62
}
結(jié)果還算正常:
1
100
2
contructor
3
5
4
50
5
hello world
6
destructor
7
上面的代碼基本演示了DLL中Class的簡單使用,包括對contructor、destrunctor的調(diào)用,有參、無參、多參函數(shù)調(diào)用,不知道有啥缺陷,但至少Work了,嘿嘿~
由上述代碼可以看出,這種“顯式”使用DLL中的Class是非常繁瑣和危險的事情,因此我覺得能用“隱式”就不要用“顯式”,能靜態(tài)就不要用動態(tài)。。。
注意到?jīng)],代碼沒有演示繼承和虛函數(shù),那是因此我加入Virtual函數(shù),程序就會core,實在搞不定,這里也就沒法給出好的方案來,不知道哪位有啥建議么。。。
上面代碼參考了如下地址:
http://www.codeproject.com/dll/classesexportedusingLL.asp http://blog.csdn.net/jdcb2001/archive/2006/11/21/1401569.aspx