我知道COM在语言和应用程序的二进制级别上提供了可重用性。 我读到为COM构建的所有组件必须遵循标准内存布局才能与语言无关。
我不明白“标准内存布局”是什么意思。
什么使COM语言独立?
答案 0 :(得分:11)
首先,一些技术背景:C ++编译器通常为任何具有虚函数的类生成一个称为“vtable”的东西。这基本上是一个函数指针表。 vtable包含一个函数指针,指向由类实现的每个虚方法。
在COM中,接口基本上是组件实现的抽象基类,例如:
class CSomeComponent : IUnknown, ISomeOtherInterface { ... };
CSomeComponent
的vtable将包含这两个接口中定义的所有方法的函数指针。
struct __imaginary_vtable_for_CSomeComponent
{
// methods required by IUnknown
HRESULT (*QueryInterface)( const IID& iid, void** ppv );
ULONG (*AddRef)();
ULONG (*Release)();
// methods required by ISomeOtherInterface
void (*foo)();
...
};
任何实例化对象都引用其动态类型的vtable。这是程序知道如何在派生类中重写基本方法的情况下调用正确的方法:
class Base
{
public:
virtual void foo() { ... }
}
class Derived : public Base
{
public:
virtual void foo() { ... } // overrides Base::foo()
virtual void bar() { ... }
}
...
Base* X = new Derived;
X->foo();
最后一行应调用Derived::foo
。这是有效的,因为对象X
引用了类Derived
的vtable。如上所述,vtable就像一个函数指针列表。现在,vtable有一个固定的布局:如果类Derived
继承自类Base
,方法foo
的函数指针将位于Derived
的vtable中的相同位置而不是Base
的vtable:
struct __imaginary_vtable_for_Base
{
void (*foo)();
};
// __imaginary_vtable_for_Base::foo = Base::foo
struct __imaginary_vtable_for_Derived
{
void (*foo)();
void (*bar)();
};
// __imaginary_vtable_for_Derived::foo = Derived::foo
现在,如果编译器看到像X->foo()
这样的东西,它知道从Base
派生的所有类的所有类,方法foo
对应于vtable中的第一个条目。因此它会调用第一个函数指针,在X
的情况下调用Derived::foo
。
回答您的问题:如果编译器为COM规范要求的vtable生成相同的布局,则编译器只能生成COM组件。 vtables可以以各种不同的方式实现,尤其是涉及多重继承时(COM组件需要)。必须遵守某种vtable格式,以便在调用组件的方法f
时,实际上调用方法f
而不是其他方法g
碰巧坐在组件类vtable中的f
位置。我认为COM兼容的编译器基本上必须生成与Microsoft Visual C ++相同的vtable布局,因为COM技术是由Microsoft定义的。
P.S。:很抱歉这么技术性,我希望上述信息对您有用。
答案 1 :(得分:4)
答案 2 :(得分:0)
标准内存布局是指在COM规范中定义(标准化)的内存布局,而不是调用或定义语言使用的默认内存布局。正是这种事情使它与语言无关!调用COM对象的特定语言中的代码在了解内存中的结构方面不必关心编写COM对象的语言。
答案 3 :(得分:0)
我记得COM,它的语言独立,就像它的结构被记录和打开(?)一样。缺点是结构是“二进制”的,并且与C / C ++密切相关,这使得很难从其他语言中使用。好消息是许多语言(如Python)都有一个C / C ++接口,这使得(Win32com Python模块)可以在其他语言中使用。
JSON是一种语言无关的,它不会直接映射到任何语言,尽管Python,Perl和Ruby(?)很接近,但几乎不可能在C / C ++中使用
希望这有某种意义