#endif // defined(DLL_EXAMPLE_MODIFIED)
class DLL_PREFIX CExample{
public:
CExample(){mpHandler = 0;}
virtual ~CExample(){}
virtual void DoCallBack(int event) = 0;
ICallBack * SetCallBackHandler(ICallBack *handler);
void Run();
private:
ICallBack * mpHandler;
};
很显然,为了给扩展DLL的导出类(增加新的虚函数)提供方便,我们必须做如下工作:
1. 增加ICallBack * SetCallBackHandler(ICallBack *handler);函数;
2. 在每个导出类的定义中增加相应的指针;
3. 定义3个宏;
4. 定义一个通用的ICallBack接口。
为了演示给CExample类增加新的虚回调函数,我在这里增加了一个ICallBack01接口的定义。很显然,新的虚回调函数应该加在新的接口中。每次DLL更新都新增一个接口(当然,每次DLL更新时,我们也可以给一个类同时增加多个虚回调函数)。
注意,每个新接口必须从上一个版本的接口继承。在我的例子中,我只定义了一个扩展接口ICallBack01。如果DLL再下个版本还要增加新的虚回调函数,我们梢栽诙ㄒ逡桓鯥CallBack02接口,注意ICallBack02接口要从ICallBack01接口派生,就跟当初ICallBack01接口是从ICallBack接口派生的一样。
上面代码中还定义了几个宏,用于定义需要检查接口版本的函数。例如我们要为新接口ICallBack01增加新函数DoCallBack01,如果我们要调用ICallBack * mpHandler; 成员的话,就应该在CExample类进行一下检查。这个检查应该如下实现:
if(mpHandler != NULL && mpHandler->GetObjectUIID()>=ICallBack01::GetClassUIID()){
((ICallBack01 *) mpHandler)->DoCallBack01(2);
}
我们看到,新回调接口增加之后,在CExample类的实现中只需简单地插入新的回调调用。
现在你可以看出,我们上述对DLL的改动并不会影响客户应用程序。唯一需要做的,只是在采用这种新设计后的第一个DLL版本(为DLL导出类增加了宏定义、回调基本接口ICallBack、设置回调处理的SetCallBackHandler函数,以及ICallBack接口的指针)发布后,应用程序进行一次重编译。(以后扩展新的回调接口,应用程序的重新编译不是必需的!)
以后如果有人想要增加新的回调处理,他就可以通过增加新接口的方式来实现(向上例中我们增加ICallBack01一样)。显然,这种改动不会引起任何问题,因为虚函数的顺序并没有改变。因此应用程序仍然以以前的方式运行。唯一你要注意的是,除非你在应用程序中实现了新的接口,否则你就接收不到新增加的回调调用。
我们应该注意到,DLL的用户仍然能够很容易与它协同工作。下面是客户程序中的某个类的实现例子:
// 如果DLL_EXAMPLE_MODIFIED没有定义,使用以前版本的DLL
#if !defined(DLL_EXAMPLE_MODIFIED)
// 此时没有使用扩展接口ICallBack01
class CClient : public CExample{
public:
CClient();
void DoCallBack(int event);
};
#else // !defined(DLL_EXAMPLE_MODIFIED)
// 当DLL增加了新接口ICallBack01后,客户程序可以修改自己的类
// (但不是必须的,如果他不想处理新的回调事件的话)
class CClient : public CExample, public ICallBack01{
public:
CClient();
void DoCallBack(int event);
// 声明DoCallBack01函数(客户程序要实现它,以处理新的回调事件)
// (DoCallBack01是ICallBack01接口新增加的虚函数)
void DoCallBack01(int event);
};
#endif // defined(DLL_EXAMPLE_MODIFIED)
例程 ---> 代码下载(6.26K)
与本文的内容配套,我提供了演示程序Dll_Hell_Solution。
1. Dll_example: DLL的实现项目;
2. Dll_Client_example: DLL的客户应用程序项目。
注意:目前Dll_Hell_Solution/Dll_example/dll_example.h文件中的DLL_EXAMPLE_MODIFIED定义被注释掉了。如果放开这个注释,可以生成更新后的DLL版本;然后可以再次测试客户应用程序。
为了保证读者能够正常演示,请遵循如下步骤:
1. 不要改动任何代码(此时DLL_EXAMPLE_MODIFIED没有定义)编译Dll_example和Dll_Client_example两个项目。运行客户程序,体验最初的情况。
2. 放开DLL_EXAMPLE_MODIFIED的注释,然后重新编译Dll_example。重新运行客户程序(此时使用了新版本的DLL),应该仍然运行正常。
3. 重新编译Dll_Client_example,生成新的客户程序。我们看到新增加的回调函数被调用了!
|
正在阅读:经典编程:DLL地狱及其解决方案经典编程:DLL地狱及其解决方案
2004-05-17 10:05
出处:CSDN
责任编辑:linjixiong
键盘也能翻页,试试“← →”键
相关文章
怎么查看进程正在调用哪些DLL文件
Win7系统取消dll文件关联的方法
win7系统玩游戏提示XINPUT1-3.dll丢失怎么处理
Win7笔记本系统如何添加注册dll和反注册dl
winxp系统开机dLL文件出错提示的具体处理步骤
360se.exe应用程序出错 计算机中丢失demaxiya.dll解决方法
pgort100.dll丢失 QQ提示pgort100.dll报错解决方法
msvcr100.dll丢失 QQ提示msvcr100.dll报错解决方法
win7 64位系统无法运行程序提示找不到tbb_debug.dll
win7旗舰版64位系统开机提示找不到comctl32.dll