Почему COM (объектная модель компонентов) не зависит от языка? - PullRequest
7 голосов
/ 09 января 2010

Я знаю, что COM обеспечивает возможность повторного использования на двоичном уровне в разных языках и приложениях. Я прочитал, что все компоненты, созданные для COM, должны соответствовать стандартной схеме памяти, чтобы быть независимыми от языка.

Я не понимаю, что означает "стандартное расположение памяти".

Что делает язык COM независимым?

Ответы [ 4 ]

11 голосов
/ 09 января 2010

Во-первых, некоторые технические знания : компиляторы C ++ обычно генерируют нечто, называемое vtable, для любого класса с виртуальными функциями. Это в основном таблица функциональных указателей. В таблице содержится указатель на функцию для каждого виртуального метода, реализуемого классом.

В COM интерфейсы - это в основном абстрактные базовые классы, которые реализует компонент, например ::10000

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

В таблицу для CSomeComponent будут включены указатели функций для всех методов, определенных в этих двух интерфейсах.

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

Любой экземпляр объекта имеет ссылку на виртуальную таблицу своего динамического типа. Вот как программа знает, как вызывать правильный метод в тех случаях, когда базовый метод переопределяется в производном классе:

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 имеет ссылку на vtable для класса Derived. Как уже говорилось, vtable похож на список указателей на функции. Теперь vtables имеют фиксированную компоновку: если класс Derived наследуется от класса Base, указатель функции для метода foo будет в том же относительном местоположении в vtable Derived, что и в vtable Base. :

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-компоненты, только если они генерируют ту же компоновку для vtables, которую требует спецификация COM. Таблицы vtables могут быть реализованы различными способами, особенно когда речь идет о множественном наследовании (что требуется для компонентов COM). Необходимо придерживаться определенного формата vtable, чтобы при вызове метода компонента f вы на самом деле вызывали метод f, а не какой-либо другой метод g, который находится в f позиция в vtable класса компонента. Я полагаю, что COM-совместимые компиляторы по сути должны создавать те же макеты vtable, что и Microsoft Visual C ++, поскольку технология COM была определена Microsoft.

P.S. : Извините за такую ​​техническую информацию, я надеюсь, что приведенная выше информация вам пригодится.

4 голосов
/ 09 января 2010

Дон Бокс написал превосходное объяснение в первой главе своей книги Essential COM. Вы можете прочитать это здесь бесплатно. Я рекомендую это.

0 голосов
/ 09 января 2010

Насколько я помню, COM не зависит от языка, так как его структура задокументирована и открыта (?). Недостатком является то, что структура является «двоичной» и тесно связана с C / C ++, что затрудняет использование из других языков. Хорошей новостью является то, что многие языки (например, Python) имеют интерфейс C / C ++, который позволяет (модуль Python Win32com) использовать из других языков.

JSON не зависит от языка в том смысле, что он не отображается напрямую ни на один язык, хотя Python, Perl и Ruby (?) Близки, но его практически невозможно использовать из C / C ++

Надеюсь, это имеет какой-то смысл

0 голосов
/ 09 января 2010

Стандартный макет памяти означает макет памяти, который определен (стандартизирован) в спецификации COM, а не тот, который по умолчанию используется вызывающим или определяющим языком.И именно это делает его независимым от языка!Код на определенном языке, вызывающий COM-объект, не должен заботиться о том, на каком языке этот COM-объект был написан, в плане знания его структуры в памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...