C# 如何围绕C风格回调创建lambda包装器?

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

我有这样的层:C主要应用程序——C++/C++包装器C++库-C++库.< /P> 编写CLI中间层是因为C#-C++互操作性的限制。我还用它从C的角度打磨了一些粗糙的边缘——换句话说,中间层允许隐藏C/C++类型(如
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;