Почему необходимо добавлять новые события в * конец * интерфейса IDL? - PullRequest
2 голосов
/ 13 мая 2009

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

Например, скажем, у меня есть следующий интерфейс:

interface IMyEvents
{
    HRESULT FooCallback(
        [in] long MyParam1,
        [in] long MyParam2,
        [in] long MyParam3);

    HRESULT BarCallback(
        [in] long MyParam1,
        [in] BSTR MyParam2,
        [in] BSTR MyParam3);
};

Теперь допустим, я хочу добавить новое событие обратного вызова, NewCallback. Если я добавлю это следующим образом, у меня не будет никаких проблем, когда событие запускается через COM:

interface IMyEvents
{
    HRESULT FooCallback(
        [in] long MyParam1,
        [in] long MyParam2,
        [in] long MyParam3);

    HRESULT BarCallback(
        [in] long MyParam1,
        [in] BSTR MyParam2,
        [in] BSTR MyParam3);

    /* New event added to the end */
    HRESULT NewCallback(
        [in] BSTR MyParam1,
        [in] BSTR MyParam2,
        [in] BSTR MyParam3);
};

Но если я добавлю это следующим образом, я могу столкнуться с различными проблемами (например, переполнением буфера) при возникновении события.

interface IMyEvents
{
    HRESULT FooCallback(
        [in] long MyParam1,
        [in] long MyParam2,
        [in] long MyParam3);

    /* New event added to the middle */
    HRESULT NewCallback(
        [in] BSTR MyParam1,
        [in] BSTR MyParam2,
        [in] BSTR MyParam3);

    HRESULT BarCallback(
        [in] long MyParam1,
        [in] BSTR MyParam2,
        [in] BSTR MyParam3);
};

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

Может кто-нибудь объяснить это поведение?

Ответы [ 2 ]

4 голосов
/ 13 мая 2009

Вы не должны изменять существующий интерфейс COM. Клиенты, которые не были скомпилированы с изменением, не знают об этом и будут продолжать звонить, как они делали до изменения.

В результате существующие клиенты вызывают BarCallback с длинным целым числом, но вместо этого получают NewCallback, который считает, что это длинное целое число является BSTR. Результаты часто бывают неприятными.

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

Однако, если у вас нет существующих клиентов в дикой природе, использующих старый интерфейс, просто убедитесь, что вы отменили регистрацию всего и заменили созданный объект, клиентов, прокси и заглушки.

0 голосов
/ 13 мая 2009

Я не думаю, что это имеет какое-либо отношение к добавлению кода в конце.

Я помню, как добавил функцию в середине файла интерфейса.

Но всякий раз, когда вы изменяете его, убедитесь, что вы отменили dll и заново создали все файлы. (как упоминалось в предыдущем посте) Будьте точны во всех шагах, потому что отладка этих вещей во время выполнения сложна.

...