gpt4 book ai didi

c# - 从 C++ COM DLL 回调到 C# 应用程序

转载 作者:塔克拉玛干 更新时间:2023-11-03 08:00:38 30 4
gpt4 key购买 nike

这将是一篇很长的文章,因为我想向您展示我尝试完成这项工作的所有步骤:)

我有 C++ COM dll,其中包含一个使用媒体基础 API 显示视频的 VideoPlayer 类。

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 对象内输出视频帧。

自定义presenter需要一个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: syntax error : expecting a type specification near "IEVRPresenterCallback"

我猜这是正常的,因为我没有在 IDL 中导入任何东西。这是正常的,因为 IEVRPresenterCallback 是在头文件中定义的。

我尝试导入头文件,但 IEVRPresenterCallback 定义的 MIDL_INTERFACE 宏生成错误:

error MIDL2025: syntax error : expecting an interface name or DispatchInterfaceName or CoclassName or ModuleName or LibraryName or ContractName or a type specification near "MIDL_INTERFACE"

然后我尝试转发声明接口(interface),但我得到了这个错误:

error MIDL2011: unresolved type declaration : IEVRPresenterCallback [ Parameter 'p_PresenterCallback' of Procedure 'RegisterCallback2' ( Interface 'IVideoPlayer' ) ]

我最后一次尝试是更改 RegisterCallback 的定义,将指针指向 IUnknown 而不是 IEVRPresenterCallback,并且在函数声明中,我将指针转换为正确的接口(interface)。

这使得 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:\Users\Public\Videos\Sample Videos\wildlife.wmv");
}
}

我遇到的问题是,尽管自定义演示者调用了回调,但我再也没有回到 C# PresentSurfaceCB 函数中。

我现在完全卡住了,我不知道问题出在哪里,也不知道如何解决:(

有什么想法吗?

提前致谢

最佳答案

多亏了汉斯,我才能让它发挥作用。

我在 IDL 文件中移动了界面,并且没有在回调中返回 ID3D9Surface 指针,而是返回了一个 DOWRD_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 对象。

关于c# - 从 C++ COM DLL 回调到 C# 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8063202/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com