作者:yanghuimin | 来源:互联网 | 2023-09-17 16:55
首先需要
强调
,当使用某个
类时
一般目的有二:
实
例化成
对
象或者
继
承它
产
生新
类
。
对
于前者,我
们
可以构造一个抽象
类
(
java
里的接口)来
连
接
调
用方和
DLL
。
抽象
类
:
// Interface.h
公共文件
/////////////////////////////////////////////////
#pragma
once
class
Interface
{
public
:
virtual void ShowMsg() = 0; //
将
调
用方需要
调
用的成
员
函数声明成
纯
虚函数
virtual ~Interface(){};//
抽象
类
的虚析构函数
};
// Interface.cpp
被
调
用方文件
////////////////////////////////////////////////
//
注意下面的代
码
并不是
实现
Interface
类
,而是因
为联
系
紧
密才写在
这
。
#include
"stdafx.h"
#include
"Test.h"
#include
"Interface.h"
//
通
过导
出函数形式向
调
用方提供指向派生
类对
象的基
类
指
针
extern
"C" __declspec(dllexport) Interface* Export(void)
{
return (Interface*)new Test();
}
|
将真正要
调
用的
类
声明成抽象
类
Interface
的派生
类
:
// Test.h
被
调
用方文件
//////////////////////////////////////////
//
类
的声明
#pragma
once
#include
"Interface.h"
class
Test:public Interface
{
public
:
Test()
virtual ~Test();
virtual void ShowMsg(void);
private
:
CString s;
};
// Test.cpp
被
调
用方文件
////////////////////////////////////////
//
类
的
实现
#include
"stdafx.h"
#include
"Test.h"
Test::Test()
{
s = "hello form dll";
}
Test::~Test()
{
AfxMessageBox(_T("destructor"));
}
void
Test::ShowMsg()
{
AfxMessageBox(s);
}
|
在
调
用方
调
用
DLL
时动态
加
载
:
//
调
用方文件
/////////////////////////////////////////////////////////
#include
"stdafx.h"
#include
"Interface.h" //
包含抽象
类
从而使用接口
//
在
调
用
处
添加如下代
码
HINSTANCE hDll;
hDll = LoadLibrary(_T("module1.dll"));//
加
载
DLL
库
文件,
DLL
名称和路径用自己的
if(hDll == NULL)
{
TRACE("/n/nload dll fail/n/n");
return;
}
typedef Interface*(*pExport)(void); //
定
义
指向
导
出函数的指
针类
型
pExport Get;
Get = (pExport)GetProcAddress(hDll,"Export");//
将指
针
指向函数首地址
if(Get == NULL)
{
TRACE("/n/nload address fail/n/n");
return;
}
Interface *t = Get();//
调
用
导
出函数
获
得抽象
类
指
针
t->ShowMsg();//
通
过该
指
针调
用
类
成
员
函数
delete t; //
释
放
DLL
中生成的
对
象
FreeLibrary(hDll); //
释
放
库
句柄
|
写到
这
第一个目的达到了。其
实
将需要
调
用的
类
的指
针
直接
导
出更
简单
,但是使用抽象
类
接口
却更加
优
雅,思路也比
较
清晰(在
这
方面
java
比
较
舒服)。
至于
继
承
DLL
中的
类
,最好的方法是使用
扩
展
DLL
。其
实
我
们应该
尽量避免
继
承
DLL
中的
类
。
动态链
接
库顾
名思
义
是可以随
时
更新
动态链
接到程序的模
块库
,目的是方便程序的模
块
化和
动
态
更新。而
继
承的本意是
为
了
实现
多
态
,多
态
的基
础
就是所有同一基
类
的派生
类
可以通
过
相同
基
类
指
针
来
访问
,基
类
是所有派生
类
的抽象,是基石,是很少甚至不可改
变
的。因此把基
类
放在
动态链
接
库
,然后从外面去
继
承他是不明智也是很奇怪的。