在实现了IUnknown之后,组件和客户之间只是一种非常松散的连接,这使用组件和客户各自可以发生变化而不会对对方造成什么影响。

下面讨论如何将组件放入到动态链接库(dll)中。

关于DLL更多内容可以参考我的其它文章:

DLL-基本概念

DLL-创建DLL

DLL-使用DLL

http://www.cnblogs.com/fangyukuan/archive/2010/06/20/1761430.html
http://www.cnblogs.com/fangyukuan/archive/2010/06/20/1761464.html
http://www.cnblogs.com/fangyukuan/archive/2010/06/21/1761666.html

组件的创建

在客户可以获取某个组件接口指针之前,它必须先将相应 的DLL装载到其进程空间中并创建此组件。这里创建组件的方法是临时性的,后面我还有其它方法(它客户和组件进一步分隔开来)。

之前说到QueryInterface函数的时候给出了CreateInstance可以建立一个组件的实例并给客户返回一个IUnknown接口指针(见:QueryInterface函数)这个函数是DLL中唯一需要显式链接的函数。客户其它所需要的所有函数都可以通过接口指针而访问到。

从DLL中输出CreateInstance函数

用extern "C"进行标记要输出的函数。

例如:

extern "C"  IUnknown *CreateInstance()

{

IUnknow *pI = (IUnknown *)(void *)new CA;

pI->AddRef();

Return pI;

}

在函数的定义前加上可防止C++ 编译器在函数名称上加上类型信息。例如在不加extern "C"时,Microsoft Visual C++ 将把CreateInstance变成:

?CreateInstance@@YAPAUUnknown@@XZ

其它的编译器可能会使用另外某种名称修改方法。

还需要建立一个的DEF文件。

LIBRARY Search.dll

EXPORTS

导出函数名

DLL的装载

CreateInstance

装载DLL并调用其中所输出的函数

为装载指定的DLL,CallCreateInstance调用了Win32的LoadLibray函数:

GetProcAddress使用LoadLibray返回的句柄和待调用的函数名称,返回一个指向此函数的指针

FARPROC GetProcAddress(

HMODULE hModule,

LPCWSTR lpProcName

);

typedef IUnknown* (*CREATEFUNCPTR)();

IUnknown* CallCreateInstance(char* name)
{
// Load dynamic link library into process.
HINSTANCE hComponent = ::LoadLibraryA(name) ;
if (hComponent == NULL)
{
cout << "CallCreateInstance:\tError: Cannot load component." << endl;
return NULL;
}

// Get address for CreateInstance function.
CREATEFUNCPTR CreateInstance
= (CREATEFUNCPTR)::GetProcAddress(hComponent, "CreateInstance");
if (CreateInstance == NULL)
{
cout << "CallCreateInstance:\tError: "
<< "Cannot find CreateInstance function."
<< endl;
return NULL;
}

return CreateInstance();
}

使用DLL的原因

DLL可以共享它们所链和的应用程序的地址空间。

客户和组件是通过接口进行交互的。一个接口实际上是一个指向函数的指针列表(vtbl)。组件为vtbl分配内存并用每个函数的地址来初始化此表格。

为了使用vtbl客户应该能 够访问组件 其vtbl民分配的内存,它还必须能够理解组件放入到vtbl中的各个地址。

进程外服务器具有与客户不同的地址空间,但我们将仍然使用Dll来帮助实现进程外服务器同客户之间的交流。如下图显示了DLL如何映射到其客户的地址空间。

此外的关键之外在于,当得到组件的一个接口指针时,连接客户和组件的唯一中介是接口的二进制结构。当客户查询组件的某个接口时,它所请求的实际上是具有特定格式的一块内存。当组件返回一个接口指针时,它告诉的实际上是些块内存的地址。

由于接口是在客户和组件都能够访问的内存中,因此这种情况实际上与当然和组件在同一个EXE文件中是相同的。

(vs2008)代码下载:http://www.box.net/shared/zhktgzojlj

本文地址:http://www.cnblogs.com/fangyukuan/archive/2010/06/09/1755150.html

COM笔记-动态链接的更多相关文章

  1. [CSAPP-II] 链接[符号解析和重定位] 静态链接 动态链接 动态链接接口

    1 平台 转http://blog.csdn.net/misskissc/article/details/43063419 1.1 硬件 Table 1. 硬件(lscpu) Architecture ...

  2. Android so 文件进阶<二> 从dlsym()源码看android 动态链接过程

    0x00  前言 这篇文章其实是我之前学习elf文件关于符号表的学习笔记,网上也有很多关于符号表的文章,怎么说呢,感觉像是在翻译elf文件格式的文档一样,千篇一律,因此把自己的学习笔记分享出来.dls ...

  3. 动态链接 - dll和so文件区别与构成

    动态链接,在可执行文件装载时或运行时,由操作系统的装载程序加载库.大多数操作系统将解析外部引用(比如库)作为加载过程的一部分.在这些系统上,可执行文件包含一个叫做import   directory的 ...

  4. Mach-O 的动态链接(Lazy Bind 机制)

    ➠更多技术干货请戳:听云博客 动态链接 要解决空间浪费和更新困难这两个问题最简单的方法就是把程序的模块相互分割开来,形成独立的文件,而不再将它们静态的链接在一起.简单地讲,就是不对那些组成程序的目标文 ...

  5. 原创 C++应用程序在Windows下的编译、链接(四)动态链接

    4动态链接 4.1概述 在静态链接阶段,链接器为PE文件生成了导入表,导出表,符号表,并调整了Call指令后面的操作数,在程序调用的时候,能够直接地或者间接地定位到IAT中的某个位置,在PE文件中,该 ...

  6. ELF动态链接

    为什么要使用动态链接? 在现代的linux系统中,假设一个普通的程序会使用到c语言静态库至少1MB以上,那么,如果我们的机器运行100个这样的程序,就用浪费近100MB的内存:如果磁盘有2000个这样 ...

  7. Delphi之DLL知识学习2---静态链接和动态链接

    静态连接 静态链接是指Delphi 编译器把要调用的函数和过程编译成可执行代码.函数的代码可存留在应用程序的 .dpr文件或一单元中.当链接用户的应用程序时,这些函数与过程便成为最终的可执行文件的一部 ...

  8. discuz x3在DIY模块中调用伪静态不成功,显示动态链接的解决办法

    discuz x3在DIY模块中调用伪静态不成功,显示动态链接,然而其他的链接正常显示伪静态. 后台启用伪静态后,发现论坛版块.帖子点击链接,伪静态正常显示,然后在门户首页DIY显示的帖子,点进去后发 ...

  9. 微信支付开发(4) 动态链接Native支付

    关键字:微信支付 微信支付v3 动态native支付 统一支付 Native支付 prepay_id 作者:方倍工作室原文: http://www.cnblogs.com/txw1958/p/wxpa ...

随机推荐

  1. [刘阳Java]_纯CSS代码实现内容过滤效果

    继续我们技术专题课,我们今天给大家带来的是一个比较酷炫的"纯CSS代码实现内容过滤效果",没有加入任何JS的效果.全部都是应用CSS3的新增选择器来实现的.先看效果截图 实现思路 ...

  2. java并发编程基础——线程通信

    线程通信 当线程在系统内运行时,程序通常无法准确的控制线程的轮换执行,但我们可以通过一些机制来保障线程的协调运行 一.传统的线程通信 传统的线程通信主要是通过Object类提供的wait(),noti ...

  3. Web 字体 font-family 浅谈

    前言 最近研究各大网站的font-family字体设置,发现每个网站的默认值都不相同,甚至一些大网站也犯了很明显的错误,说明字体还是有很大学问的,值的我们好好研究. 不同的操作系统.不同浏览器下内嵌的 ...

  4. P6295 有标号 DAG 计数

    P6295 有标号 DAG 计数 题意 求 \(n\) 个点有标号弱联通 DAG 数量. 推导 设 \(f_i\) 表示 \(i\) 个点有标号 DAG 数量(不保证弱联通),有: \[f(i)=\s ...

  5. [NOIp2017]宝藏 题解

    非常巧妙的 \(O(n^23^n)\) 做法. 题目的本质是要求一棵生成树,使得其每条边的长度与这条边的起点深度乘积的和最小. 我们使用状压 DP,考虑到当前状态与已经打通的点和深度有关,不妨设 \( ...

  6. NumPy之:多维数组中的线性代数

    目录 简介 图形加载和说明 图形的灰度 灰度图像的压缩 原始图像的压缩 总结 简介 本文将会以图表的形式为大家讲解怎么在NumPy中进行多维数据的线性代数运算. 多维数据的线性代数通常被用在图像处理的 ...

  7. 第十八篇 -- QTreeWidget应用篇 -- kuwo

    效果图: 最近学习QTreeWidget,总想着做些什么,正好学习过一点简单的爬虫,就做了一个简易的"酷我音乐下载器",界面可能不太好看,以后继续优化. ui_kuwo.py # ...

  8. vue.js 贡献指南(翻译)

    Vue.js Contributing Guide vue 2.x 嗨! 我很高兴你有兴趣为Vue.js做贡献. 在提交您的贡献之前,请务必花点时间阅读以下指南. 行为守则 问题报告指南 PR指南 开 ...

  9. LeetCode通关:求次数有妙招,位运算三连

    分门别类刷算法,坚持,进步! 刷题路线参考: https://github.com/chefyuan/algorithm-base 大家好,我是刷题困难户老三,这一节我们来刷几道很有意思的求次数问题, ...

  10. IDEA使用Tomcat时控制台乱码的解决方案>从零开始学JAVA系列

    IDEA使用Tomcat时控制台乱码的解决方案 解决方案1,修改启动时虚拟机参数 解决方案2,修改idea的设置 解决方案3,修改idea配置文件 在最后添加一行 '-Dfile.encoding=U ...