无法伪造来自 C++ 的托管回调(无法通过 static_cast 从'void (GenFlowcacheTests::*)(int)'转换为'void(*)(int)')



我用定义了一个指向托管函数的指针

typedef void(__stdcall* CounterCallback)(int count);

然后我将定义一个c++方法:

void CBSpline::GenFlowcache(/*few irrelevant parameters*/, CounterCallback func)
{/*instructions*/}

在单元测试中,我想用本机函数测试GenFlowcache

int _flowCount{};
auto Increment(int value) -> void { _flowCount = value; }
TEST_METHOD(Gen_CallbackTest)
{
// ...
sut.GenFlowcache(/**/, static_cast<CounterCallback>(GenFlowcacheTests::Increment));
}

但我找不到一种方法来铸造方法:

无法通过static_cast 从"void(GenFlowcacheTests::*((int("转换为"void(*((int(">

(编译器错误C2440(

如何将本机函数(方法、lambda等(作为CounterCallback传递

它对问题没有用处,但被管理的部分是这样的:

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);
}

然后在托管类中:

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, &parameters, strSrcDir, strTgtDir, _counter);
Marshal.FreeHGlobal(strSrcDir);
Marshal.FreeHGlobal(strTgtDir);
}
protected void CounterUpdated(int value) => FlowcacheCounter = value;

回到原生版本:

#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); }

正如john所指出的:

您可以传递类型为void(int)的函数或静态方法,也可以传递具有相同签名的非捕获lambda,仅此而已。您不能传递类型为的类方法

我可以传递一个全局函数:

int _flowCount{};
auto Increment(int value) -> void { _flowCount = value; }

将通过测试方法:

sut.GenFlowcache(/**/, (CounterCallback)Increment);

相关内容

最新更新