我翻译得绝对是差, 错漏百出(看不懂多包涵).初学win32asm编程,我找有关在asm中运用流媒体资料时找到的,为了看懂,慢慢看,猜(没办法,英语差),可惜现在还是没有这方面的资料,而且这篇还没领悟透,发上来有兴趣的看一下.对了,谁有在asm中运用wmv和DirectShow的资料给份我.谢谢
在ASM里建立一个COM objects [译者]:layper [作者]:Ernest Murphy ernie
这篇文章的例子代码为是在: masm32\COM\examples\MyCom
用于的快速编辑程序的DLL在:masm32\COM/COM/BIN/BLDDLL.bat
摘要:
---------------------------------------------------------------------------------------------------------------------
COM(零部件目标模型)基于一个非具体的实施标准(平台和语言都没被指定), 但是现实的算机世界实际给这个标准添加限制条件。
这里, 加工过程中服务器给WinTel 站台创造一简单而职能完全COM objects。 它用Visual Basic环境测试保证它符合标准。
---------------------------------------------------------------------------------------------------------------------在这里讨论的内容在MASM32包集合中。用VB6 写的Visual Basic客户机程序, 仍然设置它的形式版本为5 。 如果你用VB4 编辑VB5 版本, 它可能在早期的版本里工作,但这未测试过。 它也应该在任何VBA 里工作,但是这也没被测试过。
在这里我没有解释零部件目标模型的基础也非COM 的基本形式。 我假设您通晓这两方面和象 vtable, vtable 指针这样细节。如果您不是那么熟悉, 我建议您查找这里早先文章, 或是查找最佳的源解释Dale Rogerson 的"Inside COM"(参见参考书目) 。
因为COM 对象必须运行在真正的计算机而不是在某一课本中, 他们必须遵循仅限于那台计算机和操作系统的一定实施标准。加工过程中服务器的WinTel, 那里存在一个明确的标准装载一块代码和当不再需要卸载它: 低级的动态连接库。
从一个看法, 所有在COM 服务器程序包括是以一套5限定输出的a.DLL 。 这些是:
DllMain: 这是在任何dll里的第一个常项。当库装载时被呼叫。 它在加载过程应该检查客户(见app)服务, 如果不是检查失败。 (COM选择其它例子, 但是这里app不是。)
DllRegisterServer: 注册每个安装在系统COM对象的数据。 这个惯例自已在注册处注册组成部分。 这就是regsvr32.exe怎样能记录一个组成部分,regsvr32呼叫输出和显示返回值。
DllUnregisterServer: 当不再需要, 组成部分应该能unregister(卸载register)。 regsvr32.exe将呼叫它输出清除注册。
DllCanUnloadNow: 全局变量,在跟踪记录所有建立的对象和设置服务器为锁定(在这里解释为IClassFactory.LockServer) 。 客户app将周期性地呼叫输出检查服务器,如果服务器不再需要就卸载它。
DllGetClassObject: 最后不可思议的COM输出。 这输出带3个参数, 建立组成部分GUID, 建立GUID的接口, 并且建立指针对象。 如果这组成部分或接口不被支持, 这个惯例失败。
前4输出是简单的。DllGetClassObject 是新接触到的, 它需要更进一步的讨论。
现在, 您应该注意了的一件事是,如果这不是间接寻址COM什么也没有。间接寻址加强法则。实践中, 从DllGetClassObject 返回的对象不是我们寻找的对象: 这是"类工厂"对象。 类工厂对象是能举例(创造)其它类。这种间接方式最先指定允许对象建立的细节。如果它简单而直接返回对象的一个指针,然对象已经存在, 因此我们不能在它的建造者里确定并且控制任何参数。 DllGetClassObject 返回一个IClassFactory接口。 IClassFactory从IUnknown(当然,每个接口做)继承,这两个成员功能有:
HRESULT CreateInstance(
IUnknown * pUnkOuter, //什么时候指针分别传给A的外部对象
//REFIID riid总计,
//涉及接口标识符
oid ** ppvObject); 的输出变量//收到的输出变量的地址
//在riid申请接口指针
HRESULT LockServer(BOOL fLock);
//Increments 增值或者减量锁数
LockServer 牧举保持类工厂(如果你必须拷贝许多对象时有用) 。CreateInstance 这里是主要设备, 它习惯于建立对象的"工作"接口。CreateInstance不包括种类参考ID,它是仅仅知道怎样建立每种类的一种特别类工厂。当我们建立这种类接口时,种类ID被指定。 因而, 类工厂只会创造这成员类的接口。 目的是创建被要求的对象分类是唯一的。 如果种类需要一些特别的开始,这间接方式是有用的。 IClassFactory 是必须集中处理(总论我将没有增加什么, 在这里零部件设法对付不支持的难题) 。当然, 对于IClassFactory2,有一个定义检查组成部分申请。 为了实际上得到你的COM对象,客户程序通过产生CoCreateInstance API 功能呼叫DllGetClassObject。 这API为您处理类工厂, 并且返回被要求的接口指针 如果您只需要一个单纯功能对象, 这就是使用的功能。CoGetClassObject API 将返回给IClassFactory的指针是您的类需要进一步建立的参量。在内部, CoCreateInstance呼叫 CoGetClassObject 和通过IClassFactory举例类, 因此您总需要它定义类工厂对象创作接口。
类, 对象, 您和这些
---------------------------------------------------------------------------------------------------------------------我将偏离主题讲述一些关于怎样C++ 处理对象内部实施细节。 一位熟练C++ 程序员可能是从未充分地了解这些, 因为这是编译器为你完全处理的复杂性的水平。但是, COM 的设计师要充分充分利用概念,我们需要了解这些内容。
在C++里的++ 在语言中增加的新基本概念是类和对象。 并且对象是类的实例。 这意味我们在机器水平上探索什么。当我们在asm里写一个常规程序时, 我们依靠编译器为我们创造代码和数据段。 内存的一个区域是我们执行的代码, 另一拥有我们需要的数据。 什么++ 在C++ 为您做的是在运行时间动态地再分配数据记忆, 给类的每个实例, 代码的各小段是拥有数据段的。用一个非常正式的方式,这数据段是类的实例。种类的仅限于每个实例(或者复制)的数据储存在这个动态的数据区。 。
或许你已经听说C++ 通过额外用功能把参数隐藏拜访一个对象, 这价值。 命名这个概念的人不仅了解什么是必需, 而且有一种幽默感。当你为对象写着低级代码(在C++某编译器通常为您做的东西), 你第一问题将是 "对象是我代码?"
这是对象, 你总以这个对象运作。
这仅仅是类的实例数据存储区的一个指针。当一个对象分类功能被呼叫时,这被悄悄转移。 当私有数据对象被获取, 分类符号区域使用引用数据适合这个实例哪里。
为什么这很重要? 很简单地:一个COM接口的指针是与这指针是一样的。 我的语法规则现在疯狂提示我, 它不是正确语法如何运作。
在使用中, COM仅仅是一种接口的说明。没说明他们实际上在代码内实现怎样。实际上, 没定义写这样的细节因此实现这些接口的任何高级语言可能是一台COM服务器。 我把我的"类"数据区("对象")定义为如此:
; 宣布ClassFactory 对象结构
ClassFactoryObject STRUCT
lpVtbl DWORD 0 ; 作用平台指针
nRefCount DWORD 0; 对象和参考数
ClassFactoryObject ENDS
; 宣布MyCom 对象结构
MyComObject STRUCT
lpVtbl DWORD 0 ; 作用平台指针
nRefCount DWORD 0; 参考数
nValue DWORD 0; 接口专用数据
MyComObject ENDS
第一点是我在大范围定义这个结构。 对此COM是约定强制服从唯一的元素, 它包含DWORD指针对vtable 作用。 我也使用它为各个接口举行私有数据, 那是参考数和价值。nValue作为MyCom 接口运作与的价值, 其次将看见。 动态存储器为这些结构被以API作用CoTaskMemAlloc和释放CoTaskMemFree分配。 这些由ole32.dll输出, 这有很多其他有用的输出, 譬如检查GUID等同性, 并且从字符串中转变GUIDs。
MyCom, 一个简单的接口
对说明COM 接口工作, 我们将创造一个简单的接口称IMyCom (在COM全部接口应该适应接口有"I"前缀) 。这个连接, 象所有COM 接口, 从IUnknown 获得。它的第1个3个功能是QueryInterface,AddRef的这简单作用,并且释放。
为了增加我们的习惯接口成员, 我们增加下三名作用成员(用C设计原型):
HRESULT SetValue(long * pVal);
HRESULT GetValue(long newVal);
HRESULT RaiseValue(long newVal);
这些功能允许我们检查我们的接口功能。 SetValue和GetValue允许我们设置和读我们接口的数据成员。RaiseValue是给这数据添加价值的一个成员功能。 因而, 我们能保证自己从VB真正地访问一个完全功能的对象 。
用内存的这些结构看起来象这样:
分配结构,客户只拿这样的一个指针(ppv)。(一般ppv指针的名字来自C++ 定义"(无效)的指针的指针")" 当我们创造实例时,"对象"数据一块被分配和动态地被创建。 vtable 和服务器作用是静态的, 他们在编辑时间确定。
要注意到的一点vtable是认为给功能的指针, 他们自己是不起作用。 因而, 我们能通过改变完全"无视"继承的日常vtable指向功能。 我必须用引号说"无视",因为分类定义只是在这ASM里实施的一个精神概念,我不写类和不在其它类继承他们。 但概念是相同的。
在要遵循的例子里,有作用朝这个方向执行"忽略" 。IClassFactory 和IMyCom都从IUnknown 继承QueryInterface。 但是当他们支持不同的接口,他们需要不同的常规返回不同的结果。因而, 有二个QueryInterface 惯例(QueryInterfaceCF 和QueryInterfaceMC) 指向不同的vtables 。
简单说,至于AddRef和释放他们支持哪个接口也被定做。 这不是与AddRef一个问题, 释放不同功能MyCom必须知道怎样破坏MyCom对象。进一步提炼为未来将宣称所有对象因相似同样作用可能删除他们, 并且我们能为一切使用单个实施释放。
较少指出在从服务器内部告诉COM 连接: 完全没必要仔细审阅对象表得到一个成员指针作用: 在服务器里面这正是另一个功能,当代码确切知道在编译时间在哪里时,你能直接产生它。请认为它是一项先进的优化技术。这工作因为呼叫全部包含这些(对象指针) 作为参量, 并以此回答用"这个"对象回答"哪个"对象。
另外一个小问题, 每次客户访问我们的对象, 它通过内存从ppv 到pv 对vtable 得到产生作用的地址。如果你想要,你在目标生存期期间可以改变这个最后的指针使它展览不同的特性。有没什么在COM 合同禁止它, 虽然它是如同对自已修改代码。 我只提及它因为早先文字声称这不是真实的。 [1] [2] [3] 下一页 |