从c++ COM DLL回调到c#应用程序
Callback from a C++ COM DLL to a C# application
这将是一个很长的帖子,因为我想向你展示我试图使这个工作的所有步骤:)
我有一个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的类的实例,该实例将被设置为自定义演示者。
我已经尝试将这行添加到VideoPlayer的IDL文件中:
[id(7)] HRESULT RegisterCallback2([in] IEVRPresenterCallback * p_PresenterCallback);
但是我得到一个错误:
error MIDL2025:语法错误:期望类型规范接近"IEVRPresenterCallback"
我想这是正常的,因为我没有在IDL中导入任何东西。这很正常,因为IEVRPresenterCallback是在头文件中定义的。
我尝试导入头文件,但是IEVRPresenterCallback定义的MIDL_INTERFACE宏生成了一个错误:
error MIDL2025:语法错误:期望接口名称或DispatchInterfaceName或CoclassName或ModuleName或LibraryName或ContractName或类型规范靠近"MIDL_INTERFACE"
然后我尝试转发声明接口,但是我得到了这个错误:
错误MIDL2011: unresolved类型声明:IEVRPresenterCallback[参数'p_PresenterCallback'的过程'RegisterCallback2'(接口'IVideoPlayer')]
我的最后一次尝试是改变RegisterCallback的定义,有一个指向IUnknown的指针而不是IEVRPresenterCallback,并且在函数的声明中,我将指针转换为正确的接口。
使c++ dll正确编译。
在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:UsersPublicVideosSample Videoswildlife.wmv");
}
}
我得到的问题是,尽管自定义演示者调用回调,我从来没有回到c# PresentSurfaceCB函数。
我现在完全卡住了,我不知道问题在哪里,也不知道如何解决它。
任何想法?
Thanks in advance
多亏了Hans,我才能成功。
我在IDL文件中移动了接口,而不是在回调中返回ID3D9Surface指针,我返回一个dowd_ptr:
[
uuid(B92D8991-6C42-4e51-B942-E61CB8696FCB),
]
interface IEVRPresenterCallback : IUnknown {
[id(1)] HRESULT PresentSurfaceCB( DWORD_PTR pSurface);
}
[
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);
[id(7)] HRESULT RegisterCallback([in] IEVRPresenterCallback * p_PresenterCallback);
};
在我的WPF应用程序中,我创建了一个派生自IEVRCallback的类:
internal class EVRPresenterCallback : EmideeMediaFoundationLib.IEVRPresenterCallback
{
public void PresentSurfaceCB(uint pSurface)
{
}
}
,我把这个实例给VideoPlayer对象
- 如何使用从处理程序调度的最终回调将响应异步返回给调用方on_read?
- 调用 java 的回调() 时应用程序崩溃.由于 detatchThread 而获得运行时错误
- 通过实用程序 fn 将捕获的 lambda 传递给 C 样式回调 - 错误
- 如何将从控制台应用程序C++回调设置为C++ COM DLL
- 与Qt同时运行后台循环或回调C++应用程序?
- 安全回调提供程序(SFINAE,std::正向和过载解析)
- lambda回调中Android Cocos2D-X应用程序上的SEG故障
- 在计算机级别,应用程序以二进制方式运行,然后当发生运行时错误时,它如何呈现回错误代码
- 需要知道 Windows API 才能在我的应用程序激活时获取回调
- 如何在 android 中将C++回调作为按钮的点击处理程序传递
- 如何在Android中从本机层文件回调应用层文件
- 是否可以调用 WriteFile,应用程序将永远等待回调
- Qt 应用程序在从 <QUrl>NetworkAccessManager->get() 回调访问 QList<QLlnkedList* >时冻结
- 在Delphi应用程序中使用c++ DLL回调函数
- 从c++ COM DLL回调到c#应用程序
- 在c++中运行外部应用程序的回调
- C++,Qt,QtWebKit:如何创建一个html呈现窗口,以便您的应用程序从JS调用中获得回调
- C++,win32api:如何创建一个html呈现窗口,以便您的应用程序从JS调用中获得回调
- linux共享库支持多线程应用程序回调
- 通过JNI从c++应用程序调用Java中的c++回调