2012-02-20 3 views
0

У меня есть библиотека .NET, которая должна быть открыта для взаимодействия COM, включая некоторые асинхронные операции. Таким образом, мне нужно реализовать события. Внедрение событий из C# кажется простым:Простейший способ реализовать .NET-события для C++

[ComVisible(true)] 
[Guid("...")] 
[ClassInterface(ClassInterfaceType.None)] 
[ComSourceInterfaces(typeof(IClass1Event))] 
public class Class1: IClass1 
{ 
    public delegate Int32 IntIntFunc(Int32 arg); 
    public event IntIntFunc Event; 

    public Int32 RaiseEvent(Int32 param) 
    {...} 
} 

[ComVisible(true)] 
[Guid("...")] 
public interface IClass1 
{ 
    Int32 RaiseEvent(Int32 param); 
} 

[ComVisible(true)] 
[Guid("...")] 
public interface IClass1Event 
{ 
    Int32 Event(Int32 param); 
} 

Но у меня возникли проблемы с реализацией приемника событий на C++. Различные примеры Я встречал диапазон от простого IConnectionPoint::Advise до простого «использования VB», но я сталкиваюсь с любой проблемой, пытающейся их реализовать (и нет, я не могу использовать VB) - либо ATL отказывается реализовать AddRef для меня , или я не могу понять VTables своим умом (к сожалению, я очень разбираюсь в C-каркасах). У меня нет информации о том, какая структура предпочтительнее, только тот клиент - C++.

Итак, мой вопрос: какой бы самый простой способ показать .NET-события на C++, и, следовательно, какой был бы самый простой способ реализовать тестовый приемник?

P.S .: Действительно ли мне нужен интерфейс событий для IDispatch?

+0

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

+1

Существует много реализаций C++ для обработчиков событий, по одному я могу порекомендовать boost.signals2 (терминология отличается, но введение неплохо объясняет, что к чему, doc: http://www.boost.org/doc/ libs/1_48_0/doc/html/signals2.html) –

ответ

1

C++ vtables очень просты, если вы знакомы с COM. Microsoft в значительной степени определила их идентичность. Другими словами, MSVC++ vtable для class IUnknown двоичный, то же, что и таблица функций COM interface IUnknown.

Теперь вы, кажется, спотыкаетесь на IConnectionPoint::Advise. Это понятно. Это похоже на интерфейс, который вы должны реализовать, но это не так. Это интерфейс, реализованный источником событий. Вы используете его, чтобы сообщить источнику, какую раковину использовать.

Чтобы узнать, что произойдет, пройдите мимо объекта IUnknown и удалите его с IUnknown::QueryInterface. Конечно, вы увидите запрос источника событий для IClass1Event, по GUID. Теперь, когда вы реализуете это, вы можете вернуть его с IUnknown::QueryInterface.

Вам не нужно реализовывать интерфейс IDispatch. .Net может обойтись без; это старый Visual Basic 6, который в этом нуждается. Это потому, что VB6 слабо типизирован и требует позднего связывания.

More reading material.

+0

Спасибо за совет. Я был знаком с «IConnectionPoint», моей реальной проблемой была автоматическая реализация объекта приемника событий в VC++. Я, наконец, смог сделать это с ** объектным шаблоном ** ATL ** и ** двойным интерфейсом **. Поскольку мое решение совершенно ужасно, и это не оптимально, я все еще не могу ответить на свой вопрос ... –

Смежные вопросы