[英]cannot fake a managed callback from c++ (cannot cast from 'void (GenFlowcacheTests::*)(int)' to 'void(*)(int)' via static_cast)
I define a pointer to a managed function with:我定义了一个指向托管 function 的指针:
typedef void(__stdcall* CounterCallback)(int count);
then I'll define a c++ method:然后我将定义一个 c++ 方法:
void CBSpline::GenFlowcache(/*few irrelevant parameters*/, CounterCallback func)
{/*instructions*/}
And in a unit test, I want to test GenFlowcache
with a native function.在单元测试中,我想用原生 function 测试
GenFlowcache
。
int _flowCount{};
auto Increment(int value) -> void { _flowCount = value; }
TEST_METHOD(Gen_CallbackTest)
{
// ...
sut.GenFlowcache(/**/, static_cast<CounterCallback>(GenFlowcacheTests::Increment));
}
But I cannot find a way to cast the method:但我找不到转换方法的方法:
cannot cast from 'void (GenFlowcacheTests::*)(int)' to 'void(*)(int)' via static_cast
无法通过 static_cast 从 'void (GenFlowcacheTests::*)(int)' 转换为 'void(*)(int)'
( Compiler Error C2440 ) ( 编译器错误 C2440 )
How can I pass a native function (method, lambda etc) as CounterCallback
?如何将本机 function (方法,lambda 等)作为
CounterCallback
传递?
It is not useful for the problem, but the managed part is as such:它对问题没有用,但托管部分是这样的:
public delegate void CounterCallback(int value);
public static class CBSplines
{
[DllImport("CubicBSplines.dll", CallingConvention = CallingConvention.StdCall)]
internal static extern unsafe void GenFlowcache(IntPtr p, BroxParam* broxParam, IntPtr sourceDir, IntPtr targetDir, CounterCallback counter);
}
Then in a managed class:然后在托管 class 中:
private CounterCallback _counter;
public unsafe void GenerateFlowcache(BroxParam parameters, string sourceDir, string targetLocalDir)
{
if (_counter is null)
_counter = CounterUpdated;
if (!Directory.Exists(targetLocalDir))
Directory.CreateDirectory(targetLocalDir);
var strSrcDir = Marshal.StringToHGlobalAuto(sourceDir);
var strTgtDir = Marshal.StringToHGlobalAuto(targetLocalDir);
CBSplines.GenFlowcache(_ptr, ¶meters, strSrcDir, strTgtDir, _counter);
Marshal.FreeHGlobal(strSrcDir);
Marshal.FreeHGlobal(strTgtDir);
}
protected void CounterUpdated(int value) => FlowcacheCounter = value;
And back in native:回到本机:
#ifndef Pinvoke
#define Pinvoke extern "C" __declspec(dllexport)
#endif
Pinvoke auto GenFlowcache(CBSpline* p, BroxParam* param, const wchar_t* sourceDir, const wchar_t* targetDir, CounterCallback func)
-> void { p->GenFlowcache(param, sourceDir, targetDir, func); }
As pointed by john:正如约翰所指出的:
You can pass a function or static method typed
void(int)
you can also pass a non-capturing lambda with the same signature, and that's it.您可以传递 function 或 static 方法类型
void(int)
您也可以传递具有相同签名的非捕获 lambda ,并且You can't pass a class method however it is typed您不能通过 class 方法,但是它是键入的
I can pass a global function:我可以通过一个全局function:
int _flowCount{};
auto Increment(int value) -> void { _flowCount = value; }
that will be passed in the test method:将在测试方法中通过:
sut.GenFlowcache(/**/, (CounterCallback)Increment);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.