Это будет длинный пост, так как я хочу рассказать вам обо всех шагах, которые я пытался сделать, чтобы эта работа:)
У меня есть C ++ COM dll, который содержит класс VideoPlayer, который использует Media Foundation API для отображения видео.
Класс VideoPlayer определяется с использованием файла IDL:
[
object,
uuid(74FDBBB1-BFFB-4F7E-ACA3-ADB0C7232790),
dual,
nonextensible,
pointer_default(unique)
]
interface IVideoPlayer : IDispatch {
[id(1)] HRESULT Initialize([in] HWND* video_hwnd, [in] HWND* event_hwnd);
[id(2)] HRESULT OpenUrl([in] BSTR url_path);
[id(3)] HRESULT Play();
[id(4)] HRESULT HandleEvent([in] INT pEventPtr);
[id(5)] HRESULT Repaint(void);
[id(6)] HRESULT Resize([in] LONG width, [in] LONG height);
};
Этот класс внутренне использует собственный презентатор (основанный на проекте WPFMediaKit ), который выводит видеокадры внутри объекта IDirect3DSurface9.
Пользовательскому докладчику требуется обратный вызов типа IEVRPresenterCallback, который определяется следующим образом:
MIDL_INTERFACE("B92D8991-6C42-4e51-B942-E61CB8696FCB")
IEVRPresenterCallback : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE PresentSurfaceCB(IDirect3DSurface9 *pSurface) = 0;
};
Как видите, он не определен в файле IDL, но объявлен в заголовочном файле.
Мне нужно добавить новую функцию в класс VideoPlayer, которая позволяет вызывающему коду C # передавать экземпляр класса, унаследованного от IEVRPresenterCallback, который будет установлен для собственного презентатора.
Я пытался добавить эту строку в файл IDL VideoPlayer:
[id(7)] HRESULT RegisterCallback2([in] IEVRPresenterCallback * p_PresenterCallback);
Но я получаю ошибку:
ошибка MIDL2025: синтаксическая ошибка: ожидание спецификации типа рядом
"IEVRPresenterCallback"
Полагаю, это нормально, потому что я ничего не импортировал в IDL. Это нормально, так как IEVRPresenterCallback определен в заголовочном файле.
Я попытался импортировать файл заголовка, но макрос MIDL_INTERFACE определения IEVRPresenterCallback выдает ошибку:
ошибка MIDL2025: синтаксическая ошибка: ожидается имя интерфейса или DispatchInterfaceName или CoclassName или ModuleName или LibraryName или ContractName или спецификация типа рядом с «MIDL_INTERFACE»
Затем я попытался объявить интерфейс вперед, но я получил эту ошибку:
ошибка MIDL2011: неразрешенное объявление типа: IEVRPresenterCallback [параметр 'p_PresenterCallback' процедуры 'RegisterCallback2' (интерфейс 'IVideoPlayer')]]
Моя последняя попытка состояла в том, чтобы изменить определение RegisterCallback, чтобы указатель на IUnknown вместо IEVRPresenterCallback, и в объявлении функции я приведу указатель на правильный интерфейс.
Это заставляет dll C ++ правильно компилироваться.
В приложении C # я установил обратный вызов следующим образом:
[ComVisible(true), ComImport, SuppressUnmanagedCodeSecurity, Guid("B92D8991-6C42-4e51-B942-E61CB8696FCB"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IEVRPresenterCallback
{
[PreserveSig]
int PresentSurfaceCB(IntPtr pSurface);
}
internal class EVRPresenterCallback : IEVRPresenterCallback
{
public int PresentSurfaceCB(IntPtr pSurface)
{
return 0;
}
}
public partial class MainWindow : Window
{
private EmideeMediaFoundationLib.IVideoPlayer videoPlayer = new EmideeMediaFoundationLib.VideoPlayer();
private EVRPresenterCallback callback = new EVRPresenterCallback();
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
videoHost.VideoPlayer.RegisterCallback(callback);
videoHost.VideoPlayer.OpenUrl(@"C:\Users\Public\Videos\Sample Videos\wildlife.wmv");
}
}
Проблема, которую я получаю, несмотря на то, что пользовательский презентатор вызывает обратный вызов, я никогда не возвращаюсь в функцию C # PresentSurfaceCB.
Я сейчас застрял и не знаю, где проблема, и как ее решить: (
Есть идеи?
Заранее спасибо