簡體   English   中英

我如何創建可以從c#中調用的cpp函數,並將函數作為參數

[英]How do i create a cpp function that can be called from c# with a function as an argument

與問題完全相同。

我有一對庫,一個在cpp中,另一個在c#中。 我已經有幾個(cpp)函數,可以從c#調用,但只能使用簡單的參數(數組和基元)。

如何傳遞功能?

我在這里讀了很多答案,但是沒有一個人在幫助我-我想念什么?

這是我所擁有的:

    delegate double ManagedFunction(cli::array<System::Double>^ xIn);
    ...

    ...
    static int LevMar(
        ManagedFunction^ function,
        cli::array<System::Double, 1>^ x0,
        cli::array<System::Double, 1>^ xHigh,
        cli::array<System::Double, 1>^ xLow,
        int maxIters//,
        //double tolerance
        ) {

        IntPtr stubPointer = Marshal::GetFunctionPointerForDelegate(function);
        Unmanaged::WrapperClass::functionToMinimize = static_cast<Unmanaged::UnmanagedFunction>(stubPointer.ToPointer());

        int m = x0->Length; //nDim
        int N = 1; //observables dimension

        double* fx = new double[m];

        double* x0Arr = Utility::CreateDoubleArrayFromManaged(x0);
        double* xLowArr = Utility::CreateDoubleArrayFromManaged(xLow);
        double* xHighArr = Utility::CreateDoubleArrayFromManaged(xHigh);

        double info[LM_INFO_SZ];


        double tolerance[5];
        tolerance[0] = 0.01; //scale factor for initial \mu/ 
        tolerance[1] = tolerance[2] = tolerance[3] = tolerance[4] = 1.0e-5;

        dlevmar_bc_dif(Unmanaged::WrapperClass::functionToPassToLevMar, x0Arr, fx, m, N, xLowArr, xHighArr, NULL, maxIters, tolerance, info, NULL, NULL, NULL);
        int nElements = sizeof x0Arr / sizeof x0Arr[0];
        for (int i = 0; i < nElements; i++) x0[i] = x0Arr[0];
        return 0;
    }

所有這些都可以編譯,但是我還不能測試它,因為我不能從c#調用它。 這是我嘗試過的:

CostDelegate costDelegate = new CostDelegate(cost);
XXXCpp.Minimization.LevMar(costDelegate, x0, xhigh, xlow, 1000);

但這告訴我它不能從“ CostDelegate”轉換為“ ManagedFunction”。 兩者都是委托,並且都具有相同的簽名。

我如何才能在這里實現自我?

有沒有辦法做到這一點,以便在c#中,當我調用該函數時,我可以僅將其傳遞給一個函數而不必創建委托(即,我可以編寫cpp以便該函數使用Func<double[], double>而不是此“ ManagedFunction”對象)?

delegate double ManagedFunction(cli::array<System::Double>^ xIn);

您忘了宣布它為public 必需,兩個委托類型永遠不兼容,即使它們的簽名相同也是如此。 您的C#代碼必須創建ManagedFunction委托,只有在將其公開后才能這樣做。 考慮使用Action<array<double>^>^代替,但請閱讀下一個項目符號。

您需要注意的其他一些怪癖:

  • 注意本機代碼在函數指針上采取的調用約定。 默認值為__cdecl,但是您的委托僅與__stdcall兼容。 如果不是__stdcall,則必須應用[UnmanagedFunctionPointer]屬性來聲明調用約定。

  • stubPointer變量的一個非常棘手的問題是,在調用本機函數之前,它可能變得無效。 當程序中的其他線程運行托管代碼並且其中一個觸發垃圾回收時,這種情況很少發生。 您必須編寫GC :: KeepAlive(function); 在確保確保不會出錯的函數調用之后,這將延長報告的委托對象的生存期。

  • 復制數組效率低下,沒有必要。 您可以使用pin_ptr<double>避免這種情況。 這將生成一個指向數組第一個元素的指針,並將其固定在函數體的整個生命周期中。 本機代碼直接從GC堆尋址數組元素。

暫無
暫無

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

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