我有一些具有权威性的ANSI标准C代码。这意味着虽然我有源,但我不能翻译成另一种语言,也不能修改调用参数,因为这些操作会使权限无效。有150多个功能。

我可以进行偶然的更改,例如将文件名从.C更改为.CPP,以便使用Visual Studio 2009的C ++编译器进行编译,我已经完成了。还可以添加编译器指令等。如有必要,我也可以通过包装层。

另一个限制是我的公司希望我在任何C#代码中使用不安全的关键字。

我需要从C#程序中获取这些功能。

典型的C / C ++函数如下所示:
  double SomeFunction(double a,double [3] vec,double [3] [3] mat);
有时输入数组内容,有时输出,很少两者都输入。

我首先尝试制作一个非托管DLL(功能标记为Extern C)。只有简单参数(int,double)的函数工作正常,但我无法确定如何制作数组。 (实际上,我确实找到了一些示例代码,但复制150次非常复杂且不合理。)

然后我在同一个解决方案中尝试了两个项目,一个在C ++中,另一个在C#中。在C ++项目中,我创建了一个托管函数,它只调用了原始函数,该函数被标记为非托管。这非常干净简单,而且简单的论证也很好。但是对于数组,我找不到如何使参数类型在C#到C ++边界上匹配:
参数'2':无法从'double []'转换为'double *'
(并且如上所述,我不能使用unsafe来获取指针)。

当然,我想做的事情一定是可能的。
获得这些功能的最佳方法是什么?
(使用上述功能的示例代码非常酷。)

有帮助吗?

解决方案

示例C / C ++实现:

extern "C" __declspec(dllexport)
double SomeFunction(double a, double vec[3], double mat[3][3]) {
  double sum = a;
  for (int ix = 0; ix < 3; ++ix) {
    sum += vec[ix];
    for (int iy = 0; iy < 3; ++iy) {
      sum += mat[ix][iy];
    }
  }
  return sum;
}

示例C#用法:

private void Form1_Load(object sender, EventArgs e) {
  double[] vec = new double[3];
  double[,] mat = new double[3, 3];
  for (int ix = 0; ix < 3; ++ix) {
    vec[ix] = ix;
    for (int iy = 0; iy < 3; ++iy) {
      mat[ix, iy] = (ix + 1) * iy;
    }
  }
  double sum = SomeFunction(1, vec, mat);
}
[System.Runtime.InteropServices.DllImport("cpptemp8.dll")]
private static extern double SomeFunction(double a, double[] vec, double[,] mat);

其他提示

如果您无法使用extern和P / Invoke解决方案,那么包装器可能是您最好的选择。创建一个使用托管代码和非托管代码的托管C ++ DLL。将.NET类添加到此DLL,它只是C DLL中函数的一个瘦包装器。您的C#代码可以调用C ++ .NET类,而C ++ .NET类又将转发C函数。

通过这种方式,您可以自己编写.NET和非托管代码之间的转换,而不是依靠运行时为您完成。

使用swig,它会为你生成你的pinvoke

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top