c# - 如何使 C++ std::future 返回值适应 C# System.Threading.Tasks.Task?
问题描述
我正在包装一个要从 .NET 使用的 C++ 库。C++ API 中有一些函数返回std::future
. 我想让 .NET 代理类返回System.Threading.Tasks.Task
。
我想在 C++ 端添加一个替换方法,除了方法参数之外,它还需要一个函数指针。然后我可以启动一个新线程(std::async
例如使用)并等待std::future::get
。一旦std::future::get
返回,我可以调用传入的函数指针。在 C# 方面,我会将 a 指针传递给将完成返回的任务的函数。就像是:
Task CallCpp(int a, int b) {
TaskCompletionSource<int> tcs;
Action callback = () => tcs.SetResult(0);
IntPtr callbackPtr = Marshal.GetFunctionPointerForDelegate(callback);
CppMethod(callbackPtr, a, b);
return tcs.Task;
}
[DllExport]
external void CppMethod(IntPtr callback, int a, int b);
void CppMethod(void (*callback)(), int a, int b) {
std::future f = realmethod(a, b);
std::async([&]{ f.get; callback(); });
}
std::future realmethod(int a, int b);
(是的,代码存在内存管理问题。不过应该足以理解这个想法)
解决方案
编组异步完成或失败是相对容易的部分。我个人会使用用 C# 实现的 COM 接口,标记为[InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]
,带有 2 种方法,例如setCompleted()
and setFailed( HRESULT status )
,并在我开始任务时传递它,但这是个人喜好问题。
问题是缺少 C++ 多线程实现。
Boost 在这方面更好,它的future
类具有then
可用于在不阻塞线程的情况下传播状态的方法。
目前,标准 C++ 期货不提供任何可比的东西。我觉得你运气不好。
如果您可以修改该 C++ 库,请将 API 更改为更有意义的内容,即可以以非阻塞方式通知完成。
如果没有 COM,生命周期管理会很复杂。在您启动异步任务之后但在它完成之前,C# 端的某个人需要保留该函数指针。这是一个可能的解决方案,请注意它如何使用 GCHandle 使回调比任务更有效:
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
delegate void pfnTaskCallback( int hResult );
[DllImport( "my.dll" )]
static extern void launch( [MarshalAs( UnmanagedType.FunctionPtr )] pfnTaskCallback completed );
public static async Task runAsync()
{
var tcs = new TaskCompletionSource<bool>();
pfnTaskCallback pfn = delegate ( int hr )
{
if( hr >= 0 ) // SUCEEDED
tcs.SetResult( true );
else
tcs.SetException( Marshal.GetExceptionForHR( hr ) );
};
var gch = GCHandle.Alloc( pfn, GCHandleType.Normal );
try
{
launch( pfn );
await tcs.Task;
}
finally
{
gch.Free();
}
}
推荐阅读
- python - 将列表列表转换为列表浮动
- android - 嵌套在 Fragment 中的 SupportMapFragment 使地图不响应手势
- javascript - 处理Java脚本中的特殊字符以将它们括在方括号中?
- typescript - 为什么我不需要将 undefined 指定为返回类型?
- python - 提高性能和减少回溯所需的正则表达式帮助
- r - 从列表中返回一个列表,其中每个数据框的每一列都是字符类型
- android - 首次登录在 Android Kotlin 上抛出 401 Unaauthorized Access
- python - 带有http触发器的Python Azure函数看不到json正文
- excel - 如何截取网页截图,并将其粘贴到新电子邮件的正文中?
- amazon-web-services - 禁止在 sns:ListTopics 上使用通配符资源