簡體   English   中英

不能偽造來自 c++ 的托管回調(不能通過 static_cast 從 'void (GenFlowcacheTests::*)(int)' 轉換為 'void(*)(int)')

[英]cannot fake a managed callback from c++ (cannot cast from 'void (GenFlowcacheTests::*)(int)' to 'void(*)(int)' via static_cast)

我定義了一個指向托管 function 的指針:

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

然后我將定義一個 c++ 方法:

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

在單元測試中,我想用原生 function 測試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

如何將本機 function (方法,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);
}

然后在托管 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, &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); }

正如約翰所指出的:

您可以傳遞 function 或 static 方法類型void(int)您也可以傳遞具有相同簽名的非捕獲 lambda ,並且您不能通過 class 方法,但是它是鍵入的

我可以通過一個全局function:

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

將在測試方法中通過:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM