У меня есть следующий (связанный с DirectShow) COM-интерфейс в C++, который мне нужно вызвать на С#.
[uuid("...")] : public IUnknown
interface IBar
{
STDMETHOD(Bar)(void);
}
[uuid("...")]
interface IFoo : public IBar
{
STDMETHOD(Foo)(void);
}
Я объявил это на С# следующим, но он вылетает с нарушением доступа при вызове IFoo.Foo(). Хорошо работает с IBar.Bar(). Каков правильный способ написания эквивалентного интерфейса в С#?
[ComImport, Guid("...)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[SuppressUnmanagedCodeSecurity]
public interface IBar
{
[PreserveSig] int Bar(); // Calling this is OK
}
[ComImport, Guid("...)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[SuppressUnmanagedCodeSecurity]
public interface IFoo : IBar
{
[PreserveSig] int Foo(); // Calling this crashes
}
Vtables должны быть несовместимы в С# vs C++ для унаследованного COM-интерфейса. Есть ли способ сказать С# придерживаться объявления C++?
Ваша декларация С# для IFoo
должна выглядеть так:
[ComImport, Guid("...)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[SuppressUnmanagedCodeSecurity]
public interface IFoo
{
[PreserveSig] int Bar(); // Calling this is OK
[PreserveSig] int Foo(); // Calling this should also be OK
}
Другими словами, вы должны реплицировать методы (и макет v-таблицы) IBar
для IFoo
вместо того, чтобы извлекать из него, чтобы сделать.NET COM interop marshaller счастливым. То же самое можно сделать в C++, хотя более естественно использовать C++ наследование. Для.NET COM interop, хотя, это необходимость.
Этот метод широко используется в.NET Reference Source, например, для IOleInPlaceActiveObject, который получен из IOleWindow
.