Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么COM(组件对象模型)与语言无关?_C++_Com - Fatal编程技术网

C++ 为什么COM(组件对象模型)与语言无关?

C++ 为什么COM(组件对象模型)与语言无关?,c++,com,C++,Com,我知道COM提供了跨语言和应用程序的二进制级别的可重用性。 我了解到,所有为COM构建的组件都必须遵循标准内存布局,才能独立于语言 我不明白“标准内存布局”是什么意思 什么使COM语言独立?标准内存布局是指COM规范中定义(标准化)的内存布局,而不是调用或定义语言使用的默认布局。正是这种东西使它独立于语言!调用COM对象的特定语言的代码不必关心COM对象是用什么语言编写的,只要知道它在内存中的结构。我记得COM是独立于语言的,因为它的结构是文档化和开放的(?)。缺点是这种结构是“二进制”的,并且

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

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


什么使COM语言独立?

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

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

尽管Python、Perl和Ruby(?)非常接近,但JSON在某种程度上是独立于语言的,因此它不会直接映射到任何语言,但它几乎不可能从C/C中使用++


希望这有某种意义:

<强>第一,一些技术背景>: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();
最后一行应该调用
派生::foo
。这是因为对象
X
引用了类
派生的vtable
。如上所述,vtable就像一个函数指针列表。现在,vtables有一个固定的布局:如果class
Derived
继承自class
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
的情况下,这是对
派生::foo
的调用

回答您的问题:编译器只能生成COM组件,前提是它们生成的VTable布局与COM规范要求的布局相同。vtables可以以各种不同的方式实现,特别是当涉及到多重继承(COM组件需要多重继承)时。遵循特定的vtable格式是必要的,这样当您调用组件的方法
f
时,您实际上将调用方法
f
,而不是调用位于组件类vtable中
f
位置的其他方法
g
。我认为COM兼容编译器本质上必须产生与微软Visual C++相同的VTE布局,因为COM技术是由微软定义的。
p.S.:很抱歉这么专业,我希望以上信息对您有所帮助。

唐·博克斯在他的书《Essential COM》的第一章中写了一个很好的解释。你可以免费阅读。我推荐它。

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