【问题标题】:Why is COM (Component Object Model) language-independent?为什么 COM(组件对象模型)与语言无关?
【发布时间】:2026-01-24 21:00:01
【问题描述】:

我知道 COM 提供了跨语言和应用程序的二进制级别的可重用性。 我读到为 COM 构建的所有组件都必须遵守标准内存布局才能独立于语言。

我不明白“标准内存布局”是什么意思。

是什么让 COM 语言独立?

【问题讨论】:

    标签: c++ com


    【解决方案1】:

    首先,一些技术背景: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 就像一个函数指针列表。现在,vtables 有一个固定的布局:如果类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 的调用。

    回答您的问题:编译器只有在为 vtable 生成 COM 规范要求的相同布局时才能生成 COM 组件。 vtables 可以以各种不同的方式实现,尤其是在涉及多重继承时(这是 COM 组件所必需的)。必须遵守特定的 vtable 格式,这样当您调用组件的方法 f 时,您实际上会调用方法 f 而不是其他一些方法 g,它恰好位于 @987654342 @ 在组件类的 vtable 中的位置。我认为兼容 COM 的编译器本质上必须生成与 Microsoft Visual C++ 相同的 vtable 布局,因为 COM 技术是由 Microsoft 定义的。

    P.S.:抱歉,技术含量太高了,希望以上信息对你有用。

    【讨论】:

      【解决方案2】:

      Don Box 在他的书 Essential COM 的第一章中写了一个很好的解释。您可以免费阅读here。我推荐它。

      【讨论】:

        【解决方案3】:

        标准内存布局是指在 COM 规范中定义(标准化)的内存布局,而不是调用或定义语言使用的任何默认布局。正是这种东西使它独立于语言!调用 COM 对象的特定语言的代码不必关心 COM 对象是用什么语言编写的,就知道它在内存中的结构而言。

        【讨论】:

          【解决方案4】:

          我记得 COM 它是独立于语言的,因为它的结构被记录和开放(?)。缺点是结构是“二进制”的,并且与 C/C++ 密切相关,这使得它难以从其他语言中使用。好消息是很多语言(如 Python)都有 C/C++ 接口,这使得(Win32com Python 模块)可以从其他语言中使用。

          JSON 是独立于语言的,它不直接映射到任何语言,虽然 Python、Perl 和 Ruby (?) 很接近,但几乎不可能从 C/C++ 中使用

          希望这有某种意义

          【讨论】:

          • -1 因为声明的缺点是不正确的,因为比较 COM 和 JSON 就像比较引擎和包。
          • 嗯,是的,也不是,我认为您可以将 COM 视为客户端访问“服务器”的传输接口,就像 Web 服务一样。如果 Web 服务是基于 REST 的,它通常会使用 JSON。所以在我看来,这种比较并没有那么牵强......
          最近更新 更多