获取非托管 C++ C# 中的函数

发布于 2024-07-14 20:05:59 字数 909 浏览 6 评论 0原文

我有一些权威的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 来获取指针)。

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

I have some ANSI standard C code which is authoritative. What that means is that although I have the source, I can not translate to another language nor modify calling arguments, as those actions would invalidate the authority. There are over 150 functions.

I can make incidental changes, such as change the file names from .C to .CPP so that it compiles using Visual Studio 2009's C++ compiler, which I have done. Compiler directives and such can also be added. I can also go through a wrapper layer, if necessary.

Another restriction is my company does not want me to use the unsafe key word in any C# code.

I need to get at these functions from a C# program.

A typical C/C++ function looks like this:

double SomeFunction(double a, double[3] vec, double[3][3] mat);

Where the array contents are sometimes input, sometimes output, and rarely both.

I first tried making an unmanaged DLL (with the functions marked Extern C). Functions with only simple arguments (int, double) worked fine, but I could not determine how to Marshal the arrays. (Actually, I did find some sample code, but it was extremely complex and unreasonable to duplicate 150 times.)

I then tried two projects within the same solution, one in C++ and the other in C#. In the C++ project, I created a managed function which just called the original function which was marked as unmanaged. This was extremely clean and simple, and again, simple arguments worked fine. But for arrays, I couldn't find how to make the argument types match across the C# to C++ boundary:
Argument '2': cannot convert from 'double[]' to 'double*'
(and as mentioned above, I can't use unsafe to get a pointer).

Certainly what I am trying to do must be possible.
What is the best way to get at these functions?
(Sample code using the above function would be really cool.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

暮年慕年 2024-07-21 20:05:59

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);

Sample C/C++ implementation:

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;
}

Sample C# usage:

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);
双手揣兜 2024-07-21 20:05:59

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

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

If you can't get the extern and P/Invoke solution to work, a wrapper is probably your best bet. Create a managed C++ DLL that uses both managed and unmanaged code. Add a .NET class to this DLL that is just a thin wrapper over the functions in your C DLL. Your C# code can call the C++ .NET class, which will in turn forward on the C functions.

This way you can write the translation between .NET and unmanaged code yourself, instead of relying on the runtime to do it for you.

爱,才寂寞 2024-07-21 20:05:59

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

use swig, it will generate your pinvoke for you

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文