C# 如何围绕C风格回调创建lambda包装器?
我有这样的层:C主要应用程序——C++/C++包装器C++库-C++库.< /P> 编写CLI中间层是因为C#-C++互操作性的限制。我还用它从C的角度打磨了一些粗糙的边缘——换句话说,中间层允许隐藏C/C++类型(如C# 如何围绕C风格回调创建lambda包装器?,c#,visual-c++,lambda,c++-cli,C#,Visual C++,Lambda,C++ Cli,我有这样的层:C主要应用程序——C++/C++包装器C++库-C++库.< /P> 编写CLI中间层是因为C#-C++互操作性的限制。我还用它从C的角度打磨了一些粗糙的边缘——换句话说,中间层允许隐藏C/C++类型(如char*)并进行所有必要的转换 我无法进行的一个转换是传递回调。我尝试按中的方式执行此操作,但无法将lambda作为回调传递 C++回调定义: typedef void (*CppOnEngineCloseCallback) (void * customParam, co
char*
)并进行所有必要的转换
我无法进行的一个转换是传递回调。我尝试按中的方式执行此操作,但无法将lambda作为回调传递
C++回调定义:
typedef void (*CppOnEngineCloseCallback)
(void * customParam, const wchar_t * errorMessage);
我知道没有使用customParam
,所以我为中间层(CLI/C++)定义了这样的回调:
在包装器中,我创建了这样的lambda:
// lambda signature should resemble CppOnEngineCloseCallback
auto lambda = [&] (void * customParam, const wchar_t * errorMessage) {
cli_callback(Marshal::PtrToStringUni( IntPtr(static_cast<void*>(
const_cast<wchar_t*>(errorMessage)))));
};
它表示无法将lambda
转换为CppOnEngineCloseCallback
首先它可行吗?如何?< p>你使用<代码> Audio/Cuff>,因此你隐藏了实际的类型,并且让你自己更难管理C++强类型安全。 可能lambda函数不是正确的类型,或者至少不是您期望的类型
CppOnEngineCloseCallback
可能是函数指针类型(或std::function类型)。因此,为了帮助您自己,请尝试将
lambda
的类型更改为预期的类型,并查看编译器的说明
CppOnEngineCloseCallback lambda = [&] (void * customParam, const wchar_t * errorMessage) {
cli_callback(Marshal::PtrToStringUni( IntPtr(static_cast<void*>(
const_cast<wchar_t*>(errorMessage)))));
};
通常,不可能将lambda强制转换为函数指针。 正如您所知,lambda是编译器生成的类的对象,其行为仅类似于函数 对于实际问题:您提到没有使用
customParam
典型的模式是,customParam
由库的调用者提供,并在回调函数中用于标识处理回调的某些对象。在回调函数中,映射到实际要调用的函数:
void MyNativeCallback(void*customParam,const wchar\u t*errorMessage)
{
静态_cast(customParam)->回调(errorMessage);
}
因此,您可以将指向lambda的指针作为customParam传递给库,并提供一个如上所述的帮助函数作为回调函数。无论如何,正确获取指针类型并不是一项简单的任务。我更喜欢一个小助手班。谢谢
CppOnEngineCloseCallback
是一个函数指针,如我的问题(第一个代码段)所示。将auto
更改为CppOnEngineCloseCallback
只会将错误(消息完全相同)移动到具有lambda
定义的行。@greenoldman我编辑了我的答案,解释了如何使用[]
而不是[&]
。或者改用std::function
再次感谢,但是cli\u callback
位于本地范围,我需要捕获它。当我只为捕获指定它时,我返回到原始错误。我不能修改C++层(库中的一个),只有CLI/C++和C ^。@ GrimoLdman然后可以定义一个适当的方法,而不是lambda,使clii回调可访问。但是理论上,你所做的是可能的,一旦你修复了编译错误,你只需要让正确的参数可以访问,
InitEngine( // C++ function that requires callback
&lambda);
CppOnEngineCloseCallback lambda = [&] (void * customParam, const wchar_t * errorMessage) {
cli_callback(Marshal::PtrToStringUni( IntPtr(static_cast<void*>(
const_cast<wchar_t*>(errorMessage)))));
};
typedef std::function<void(void *, const wchar_t *)> CppOnEngineCloseCallback;