为什么COM(组件对象模型)与语言无关? [英] Why is COM (Component Object Model) language-independent?

查看:222
本文介绍了为什么COM(组件对象模型)与语言无关?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道COM在语言和应用程序的二进制级别提供可重用性。
我读到所有为COM构建的组件必须遵守标准的内存布局,以便与语言无关。



我不明白什么是标准内存

解决方案

> 首先,一些技术背景:C ++编译器通常为任何带有虚函数的类生成一个名为vtable的东西。这基本上是一个函数指针表。



在COM中,接口基本上是一个组件实现的抽象基类,例如:

  class CSomeComponent:IUnknown,ISomeOtherInterface {...}; 

CSomeComponent 的vtable将包括函数指针对于这两个接口中定义的所有方法。

  struct __imaginary_vtable_for_CSomeComponent 
{
// IUnknown
HRESULT(* QueryInterface)(const IID& iid,void ** ppv);
ULONG(* AddRef)();
ULONG(* Release)();
// ISomeOtherInterface所需的方法
void(* foo)();
...
};

任何实例化的对象都具有对其动态类型的vtable的引用。这是程序知道如何在派生类中重载基本方法的情况下如何调用正确的方法:

  Base 
{
public:
virtual void foo(){...}
}

类派生:public Base
{
public:
virtual void foo(){...} //覆盖Base :: foo()
virtual void bar(){...}
}

...

Base * X = new Derived;
X-> foo();

最后一行应该调用 Derived :: foo 。这是因为对象 X 具有对 Derived 的vtable的引用。如上所述,vtable就像一个函数指针列表。现在,vtables有一个固定的布局:如果 Derived 类继承自 Base ,函数指针$ c> 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组件,如果它们为COM规范要求的vtables生成相同的布局。 vtables可以以各种不同的方式实现,特别是当涉及到多重继承(这是COM组件所必需的)。必须遵守一定的vtable格式,以便在调用组件的方法 f 时,您将实际调用方法 f ,而不是一些其他方法 g ,它位于 f 组件类的vtable。我认为COM兼容的编译器本质上必须产生与Microsoft Visual C ++相同的vtable布局,因为COM技术是由Microsoft定义的。



PS :对不起,因为这么技术,我希望以上信息是对你有一些使用。


I know that COM provides reusability at the binary level across languages and applications. I read that all components built for COM must adhere to a standard memory layout in order to be language-independent.

I do not understand what "standard memory layout" means.

What makes COM language-independent?

解决方案

First, some technical background: C++ compilers usually generate something called a "vtable" for any class with virtual functions. This is basically a table of function pointers. The vtable contains a function pointer to every virtual method implemented by a class.

In COM, interfaces are basically abstract base classes which a component implements, e.g.:

class CSomeComponent : IUnknown, ISomeOtherInterface  { ... };

The vtable for CSomeComponent will include function pointers for all methods defined in these two interfaces.

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)();
    ...
};

Any instantiated object has a reference to the vtable of its dynamic type. This is how the program knows how to call the proper method in cases where a base method is overridden in a derived class:

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();

The last line should call Derived::foo. This works because object X has a reference to the vtable for class Derived. As said, the vtable is like a list of function pointers. Now, vtables have a fixed layout: If class Derived inherits from class Base, the function pointer for method foo will be at the same relative location in Derived's vtable than in Base's 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

Now, if the compiler sees something like X->foo(), it knows that all for all classes derived from Base, method foo corresponds to the first entry in the vtable. So it issues a call to the first function pointer, which in X's case is a call to Derived::foo.

Answer to your question: Compilers can only generate COM components if they generate the same layout for vtables that the COM specification demands. vtables can be implemented in various different ways, especially when it comes to multiple inheritance (which is required with COM components). Adhering to a certain vtable format is necessary so that when you call a component's method f, you will actually call method f and not some other method g which happens to sit at f's position in the component class's vtable. I suppose COM-compliant compilers essentially have to produce the same vtable layouts as Microsoft Visual C++, since the COM technology was defined by Microsoft.

P.S.: Sorry for being so technical, I hope the above information is of some use to you.

这篇关于为什么COM(组件对象模型)与语言无关?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆