[英]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堆尋址數組元素。
您是否已閱讀過如何:定義和使用委托(C ++ / CLI) ?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.