从C#获取非托管C函数

 2021-04-27 

Getting at unmanaged C++ functions from C#

我有一些权威的ANSI标准C代码。这就是说,尽管我有原文,但我不能翻译成另一种语言,也不能修改调用参数,因为这些动作会使授权无效。有超过150个功能。

我可以进行偶然的更改,例如将文件名从.C更改为.CPP,以便使用Visual Studio 2009的C编译器进行编译。也可以添加编译器指令等。如有必要,我还可以遍历package层。

另一个限制是我的公司不希望我在任何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边界匹配:
Argument '2': cannot convert from 'double[]' to 'double*'
(并且如上所述,我不能使用不安全的方法来获取指针)。

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


示例C / C实现:

1
2
3
4
5
6
7
8
9
10
11
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#用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
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);


如果您无法使用外部和P / Invoke解决方案,那么package可能是最好的选择。创建同时使用托管代码和非托管代码的托管C DLL。向此DLL添加一个.NET类,该类只是对C DLL中的函数的一个简单package。您的C#代码可以调用C .NET类,该类将依次在C函数上进行。

这样,您可以自己编写.NET和非托管代码之间的转换,而不必依赖运行时为您完成转换。


使用swig,它将为您生成拼音