[英]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.