在我的C ++代码中,回调函数表示为std :: function()obj,而不是更常见的函数指针构造。
typedef std::function<void()> MYCALLBACK;
C ++中的回调函数通过以下方式设置:
MYCALLBACK myCBFunc; // some member variable
void SetCallbackFunction(MYCALLBACK cbFunc)
{
myCBFunc = cbFunc;
}
在C#中:
delegate void MyCallbackFunc(); // delegate matching the c++ callback sig
// method matching the call back sig
void foo()
{ }
[DllImport("mydll.dll")]
static extern SetCallbackFunction(MyCallbackFunc cbfunc);
// set the callback
MyCallbackFunc cb = foo;
SetCallbackFunction(cb); // crash here
编译好,但运行时遇到AccessViolationException崩溃。 我最初认为这是因为MYCALLBACK obj在堆栈上,并且需要通过引用传递并更改签名以匹配但它仍然崩溃,即。
MYCALLBACK myCBFunc; // some member variable
void SetCallbackFunction(MYCALLBACK& cbFunc)
{
myCBFunc = cbFunc;
}
[DllImport("mydll.dll")]
static extern SetCallbackFunction(ref MyCallbackFunc cbfunc);
// set the callback
MyCallbackFunc cb = foo;
SetCallbackFunction(ref cb); // crash here
我如何使用std :: function()?使用普通的旧函数指针没有问题。
答案 0 :(得分:2)
std::function<void()>
是一个类模板。它看起来像一个函数,因为类重载operator()
。因此,std::function<void()>
是一个类意味着它不是与非托管函数指针二进制兼容。
您需要使用:
typedef void (*MYCALLBACK)();
请注意,此函数是cdecl。在C ++中将其切换为stdcall,或将C#delegate声明为cdecl。我希望你知道怎么做前者。以下是后者的一个例子:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void MyCallbackFunc();
你的pinvoke也是错误的,因为它不应该将回调作为ref
参数传递。它应该是:
[DllImport("mydll.dll")]
static extern SetCallbackFunction(MyCallbackFunc cbfunc);