ChiefSailor的歪酷Blog
 
« 上一篇: MFC DLL向导(1) 下一篇: .Net中常见问题及解决方法归类 »
chiefsailor @ 2006-06-13 23:52

 使用DLL的一个比较严重的问题就是编译器之间的兼容性问题。不同的编译器对c++函数在二进制级别的实现方式是不同的。所以对基于C++的DLL,如果编译器不同就有很麻烦的。如果创建的是MFC扩展DLL,就不会存在问题,因为它只能被动态连接到MFC的客户应用程序。这里不是本文讨论的重点。

一、重新编译问题
我们先来看一个在实际中可能遇到的问题:
    比如现在建立好了一个DLL导出了CMyClass类,客户也能正常使用这个DLL,假设CMyClass对象的大小为30字节。如果我们需要修改DLL中的CMyClass类,让它有相同的函数和成员变量,但是给增加了一个私有的成员变量int类型,现在CMyClass对象的大小就是34字节了。当直接把这个新的DLL给客户使用替换掉原来30字节大小的DLL,客户应用程序期望的是30字节大小的对象,而现在却变成了一个34字节大小的对象,糟糕,客户程序出错了。
    类似的问题,如果不是导出CMyClass类,而在导出的函数中使用了CMyClass,改变对象的大小仍然会有问题的。这个时候修改这个问题的唯一办法就是替换客户程序中的CMyClass的头文件,全部重新编译整个应用程序,让客户程序使用大小为34字节的对象。
    这就是一个严重的问题,有的时候如果没有客户程序的源代码,那么我们就不能使用这个新的DLL了。

二、解决方法  
 为了能避免重新编译客户程序,这里介绍两个方法:(1)使用接口类。(2)使用创建和销毁类的静态函数。
1、使用接口类
   接口类的也就是创建第二个类,它作为要导出类的接口,所以在导出类改变时,也不需要重新编译客户程序,因为接口类没有发生变化。
   假设导出的CMyClass类有两个函数FunctionA FunctionB。现在创建一个接口类CMyInterface,下面就是在DLL中的CMyInterface类的头文件的代码:
# include "MyClass.h"
class _declspec(dllexport) CMyInterface
{
     CMyClass *pmyclass;
     CMyInterface();
     ~CMyInterface();
  public:
     int FunctionA(int);
     int FunctionB(int);
};
而在客户程序中的头文件稍不同,不需要INCLUDE语句,因为客户程序没有它的拷贝。相反,使用一个CMyClass的向前声明,即使没有头文件也能编译:
class _declspec(dllexport) CMyInterface
{
     class CMyClass;//向前声明
     CMyClass *pmyclass;
     CMyInterface();
     ~CMyInterface();
  public:
     int FunctionA(int);
     int FunctionB(int);
};
在DLL中的CMyInterface的实现如下:
CMyInterface::CMyInterface()
{
      pmyclass = new CMyClass();
}
CMyInterface::~CMyInterface()
{
     delete pmyclass;
}
int CMyInterface::FunctionA()
{
     return pmyclass->FunctionA();
}
int CMyInterface::FunctionB()
{
     return pmyclass->FunctionB();   
}
.....
对导出类CMyClass的每个成员函数,CMyInterface类都提供自己的对应的函数。客户程序与CMyClass没有联系,这样任意改CMyClass也不会有问题,因为CMyInterface类的大小没有发生变化。即使为了能访问CMyClass中的新增变量而给CMyInterface类加了函数也不会有问题的。
   但是这种方法也存在明显的问题,对导出类的每个函数和成员变量都要对应实现,有的时候这个接口类会很庞大。同时增加了客户程序调用所需要的时间。增加了程序的开销。

2、使用静态函数
   还可以使用静态函数来创建和销毁类对象。创建一个导出类的时候,增加两个静态的公有函数CreateMe()/DestroyMe(),头文件如下:
class _declspec(dllexport) CMyClass
{
     CMyClass();
     ~CMyClass();
  public:
     static CMyClass *CreateMe();
     static void DestroyMe(CMyClass *ptr);
};
实现函数就是:
CMyClass * CMyClass::CMyClass()
{
      return new CMyClass;
}
void CMyClass::DestroyMe(CMyClass *ptr)
{
      delete ptr;
}
然后象其他类一样导出CMyClass类,这个时候在客户程序中使用这个类的方法稍有不同了。如若想创建一个CMyClass对象,就应该是:
CMyClass x;
CMyClass *ptr = CMyClass::CreateMe();
在使用完后删除:
CMyClass::DestroyMe(ptr);

参见:http://dev.csdn.net/author/housisong/a38c9661-fa3b-43ce-ad19-b84c7cdc4214.html
作者:laiyiling 





评论 / 个人网页 / 扔小纸条
* 昵称

已经注册过? 请登录

新用户请先注册 以便能显示头像及追踪评论回复

Email
网址
* 评论
表情
 


 

分类小组论坛
杂谈 , 娱乐、八卦 , 文学、艺术 , 体育 , 旅游、同城 , 象牙塔 , 情感 , 时尚、生活 , 星座 , 科技

请注意遵守中华人民共和国法律法规, 如威胁到本站生存, 将依法向有关部门报告, 同时本站的相关记录可能成为对您不利的证据.

相关法律法规
全国人大常委会关于维护互联网安全的决定
中华人民共和国计算机信息系统安全保护条例
中华人民共和国计算机信息网络国际联网管理暂行规定
计算机信息网络国际联网安全保护管理办法
计算机信息系统国际联网保密管理规定

日历
网志分类
· 所有网志
· 生活点滴
· 学习生涯
· 物语
· 我贫我掰
· C/C++
· 技术文档
· .NET
· JAVA
· Linux
· Network
· Database
精华文章
人生必看十大动画片
历届奥斯卡奖获奖名单回顾
帮你参悟人生十个故事
冷评热论央视记者
考研吧,悟空!
国内热门软件作者真人照片(多图)
C++程序设计之四书五经(上)
C++程序设计之四书五经(下)
C++资源之不完全导引(上)
C++资源之不完全导引(下)