惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
NISL@THU
NISL@THU
E
Exploit-DB.com RSS Feed
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
K
Kaspersky official blog
Project Zero
Project Zero
Cisco Talos Blog
Cisco Talos Blog
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
S
Schneier on Security
G
GRAHAM CLULEY
The Hacker News
The Hacker News
T
Threat Research - Cisco Blogs
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy & Cybersecurity Law Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Cyberwarzone
Cyberwarzone
C
CERT Recently Published Vulnerability Notes
T
Tor Project blog
AWS News Blog
AWS News Blog
Simon Willison's Weblog
Simon Willison's Weblog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
爱范儿
爱范儿
P
Privacy International News Feed
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
S
Securelist
G
Google Developers Blog
The Last Watchdog
The Last Watchdog
Google Online Security Blog
Google Online Security Blog
美团技术团队
F
Fortinet All Blogs
小众软件
小众软件
Recorded Future
Recorded Future
V
Visual Studio Blog
B
Blog RSS Feed
H
Help Net Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
Blog — PlanetScale
Blog — PlanetScale
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
Martin Fowler
Martin Fowler
Latest news
Latest news
Spread Privacy
Spread Privacy
H
Heimdal Security Blog

博客园 - 孔曰成仁,孟曰取义

没有终结点在侦听可以接受消息的...另外一种排错方式 VS2010 sp1 & Windows SDK 7.1 正确安装步骤 ORA-28001 vs2010 序列号 全身“大扫除”五方案 转载 typedef大全 MFC的DLL 概述 [转]MFC .DLL指南(一) [转]VC下发布的Release版程序的异常捕捉 [转]调试Release版本应用程序,不知道转自哪里 [转]VC调试篇-不知道转自何处 对“仅通过崩溃地址找出源代码的出错行”一文的补充与改进,转自vckbase,记录一下 - 孔曰成仁,孟曰取义 - 博客园 仅通过崩溃地址找出源代码的出错行,转自老罗,记录一下 [转]Release版程序调试排错技巧 老公是用来欺负,老婆是用来疼的!(猪公猪婆篇) 网站汇总 近日探得用C++将二进制数据存储到XML文件的方法,因在研究时,未得到网上其他同仁的帮助(网上搜索了半天没有相关资料,只有DOTNET的),在这里不敢独享,给别的同仁在搜索时能够搜索到相关资料,也算是绵薄之力! ) 近日发现vs2005安装的一个问题 近日发现vs2005安装的一个问题
MFC .DLL指南(二)
孔曰成仁,孟曰取义 · 2008-05-06 · via 博客园 - 孔曰成仁,孟曰取义

我们上节讨论的结果是.DLLs对于任何的程序员都是非常实用的工具.然而,使用他们却有很多限制,任何人在作的时候都要意识到这点.

  MFC Issues
  在上一节已经提到了这个,但是很有再一次提的价值.MFC扩展的.DLL只能在和客户端的程序用相同的MFC和正确的MFC的代码库的情况下才好使.正规的.DLL也是如此.

  Compiler Incompatibility Issues
  一个很重要的问题就是在以C++为基础的.DLLs,当它们建立在某一个编译器上,而调用它们的客户端却建立在另一个编译器上,通常情况下,再多的努力,它也不会工作.:(
  ANSI协会制定了C和C++的语言的标准.也就是说,它指定了C和C++的函数和数据类型必须由一个编译器来支持.但是它并没有提供一个完整的基于二进制级的关于如何用函数和数据类型的实现.结果,编译器厂商就根据自己的方式来自由的实现其语言功能.
  很 多的C/C++程序员知道不同的编译器操作的数据类型是不同的.一个编译器为int型变量分配2bytes,但另一个也许会分配4bytes.一个会用 4bytes的double,另一个可能用8bytes的.在函数实现和操作符重载方面就有更大的差别了.不同的编译器的差别比你想的还要多,所以,这些 不同使你的.DLL不能运行于某些的程序上.
  编译器的不兼容问题可以通过插入pragmas和其他的重编译说明到你的代码来解决,但是很难, 而且不易读.但是用到不兼容的编译器确实是不可避避免的.解决编译器不兼容问题的最好的方法是让你的.DLL导出一个简单的接口类,让它指回你 的.DLL,我们将在下面讨论.

  Recompiling
  让我们假设你建立了内含名为CMyClass的类的.DLL.当一个客户程序连到你的.DLL,.DLL创建这个类的实例并导出这个实例.假设你的导出实例为30字节.
  现 在假设你对CMyClass做了一些改动,加了一个int型变量,这样你的导出的CMyClass的实例就由原来的30字节变成了34字节,你将新 的.DLL给用户,让它替代原来的.现在,错误来了,客户程序期待一个30字节的实例,但是你的新的.DLL却送来了34字节的实例,客户程序将抛出异 常.
  客户程序并不需要改变代码,所有要做的就是导入一个CMyClass类的实例.在代码的某处,加上这行:

     _declspec(dllimport) CMyClass myObject;

  客户程序的代码不需任何改变,只需要重编译客户程序来解决此问题,重编译后,客户程序将等待34字节的实例.
  这是很严重的问题,不重新编译客户端而只在改变.DLL后将此.DLL重置是我们的目标.然而,你的.DLL要导出整个类或一个类的实例,那么此目标是不可能实现的.你必须重编译客户端.如果你没有客户端的源代码,你将使用不了新的.DLL.

  Solutions
  如果对上面的问题有一个很好的解决,那么我们不会用COM了.这里有一些建议:
  尽可能的用MFC的扩展的.DLLs.虽然这样限制了你的客户程序的类型,但是解决了编译器不兼容的问题.
  如果你的.DLL导出类或者类的实例,你不得不在修改了.DLL后重新编译你的客户端.为了避免这样,你必须做到分解你要导出的类,实现导出类的一个接口.最好的方法是,创建一个作为第一个类的接口的类,这样你改变了导出类的话,接口类不变,客户程序无需重新编译.
  这 里有一个例子.假设你要导出CMyClass类.CMyClass有两个公有函数,int FunctionA(int)和 int FunctionB(int).替代导出CMyClass,我将创建一个导出接口CMyInterface.CMyInterface将含有一个 指向CMyClass的实例.这里给出它的头文件:
  
     class AFX_EXT_CLASS CMyInterface
     {
          class CMyClass; //forward declaration of CMyClass
          CMyClass *m_pMyClass;
          
          public:
          CMyInterface( );
          ~CMyInterface( );
          
          int FunctionA(int);
          int FunctionB(int);
     };

  这份头文件将用在.DLL和客户端程序.注意,前面的声明意味着没有CMyClass的备份也可以编译.
  在.DLL内部,这样实现CMyInterface:

     CMyInterface::CMyInterface( )
     {
          m_pMyClass = new CMyClass; 
     }
     
     ~CMyInterface::~CMyInterface( )
     {
          delete m_pMyClass;
     }
     
     CMyInterface::FunctionA( )
     {
          return m_pMyClass->FunctionA( );
     }
     
     CMyInterface::FunctionB( )
     {
          return m_pMyClass->FunctionB( );
     }

  因 此,CMyClass的每一个函数,CMyInterface将提供相应的函数.客户程序将和客户程序没有联系.如果它想调用 CMyClass::FunctionA,只需调用CMyInterface::FunctionA.接口类会用指针调用CMyClass.用这种布局你 可以改变CMyClass了----不用担心CMyClass的大小变了.CMyInterface的接口的大小不变.即使你给CMyClass加了一个 私有变量,CMyInterface的大小也不会变.要是你加了公有成员,就在CMyInterface里边直接加上对应新变量 的"getter" 和 "setter" 函数,不用担心,加入新的函数,CMyInterface接口类的大小不会改变.
  建立一个单独的 接口可以避免编译器不兼容,客户端重编译的问题.只要接口类不变,就不需重编译.但仍然有两个小问题,一:对于每一个CMyClass的公有的成员变量, 你必须在CMyInterface里创建实际的对应的函数或变量.这个例子中只有两个函数,所以很简单.如果CMyClass有成千上万的函数和变量,这 将变得很困难,而且易错.二:你将增大进程的开销.客户程序不再直接访问CMyClass,替代的通过访问CMyInterface来访问 CMyClass.如果一个函数要被调用成千次,那此进程将会耗用很长时间.