如何从C#的char*向非托管C++DLL传递和接收数据

本文关键字:C++DLL 数据 char | 更新日期: 2023-09-27 18:29:27

  • 我没有完全访问DLL源的权限,只有标头
  • 实际代码中的参数名称更具描述性

我试图调用一个非托管DLL,该DLL接收所有的char*变量,其中两个变量充当";返回";价值观in1-8是输入,in9和10是长度为512的char*,并且以空形式传递。一旦调用完成,就应该用结果数据填充它们。

以下是我尝试使用的示例定义:

[DllImport("mydll.dll")]
public static extern IntPtr foo(
    IntPtr in1,
    IntPtr in2,
    IntPtr in3,
    IntPtr in4,
    IntPtr in5,
    IntPtr in6,
    IntPtr in7,
    IntPtr in8,
    ref IntPtr result1,
    ref IntPtr result2);

这是我的电话:

IntPtr param1 = Marshal.StringToHGlobalUni("testdata");
IntPtr param2 = Marshal.StringToHGlobalUni("testdata");
IntPtr param3 = Marshal.StringToHGlobalUni("testdata");
IntPtr param4 = Marshal.StringToHGlobalUni("testdata");
IntPtr param5 = Marshal.StringToHGlobalUni("testdata");
IntPtr param6 = Marshal.StringToHGlobalUni("testdata");
IntPtr param7 = Marshal.StringToHGlobalUni("testdata");
IntPtr param8 = Marshal.StringToHGlobalUni("testdata");
IntPtr param9 = IntPtr.Zero;
IntPtr param10 = IntPtr.Zero;
foo(param1, param2, param3, param4, param5, param6, param7, param8, ref param9, ref param10);

要打印IntPtr,我正在执行:

string str = Marshal.PtrToStringUni(param9);
Console.WriteLine(str);

在一个";样品";给我的C++调用是这样的:

char result1[512]="";
char result2[512]="";
foo("testdata", "testdata", "testdata", "testdata", "testdata", "testdata", "testdata", "testdata", result1, result2);
printf("%s,%s'n",result1,result2);

问题:在我尝试过的所有方法中,包括char[512]转换为byte[]、StringBuilder size 512、IntPtr等。每次返回时param9和param10的值都是空的。有人能帮我弄清楚吗?提前谢谢。

编辑在下面的一些有用的评论和更多的谷歌搜索之后,我修补了我混乱的代码。编辑如下:

[DllImport("mydll.dll")]
public static extern IntPtr foo(
    IntPtr in1,
    IntPtr in2,
    IntPtr in3,
    IntPtr in4,
    IntPtr in5,
    IntPtr in6,
    IntPtr in7,
    IntPtr in8,
    IntPtr result1,
    IntPtr result2);

我去掉了两个结果char数组上的ref。

IntPtr param1 = Marshal.StringToHGlobalAnsi("testdata");
IntPtr param2 = Marshal.StringToHGlobalAnsi("testdata");
IntPtr param3 = Marshal.StringToHGlobalAnsi("testdata");
IntPtr param4 = Marshal.StringToHGlobalAnsi("testdata");
IntPtr param5 = Marshal.StringToHGlobalAnsi("testdata");
IntPtr param6 = Marshal.StringToHGlobalAnsi("testdata");
IntPtr param7 = Marshal.StringToHGlobalAnsi("testdata");
IntPtr param8 = Marshal.StringToHGlobalAnsi("testdata");
IntPtr param9 = Marshal.AllocHGlobal(512 * sizeof(int));
IntPtr param10 = Marshal.AllocHGlobal(512 * sizeof(int));
foo(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);

上面我分配了param9和10,而不是IntPtr.Zero

//printing..
string str = Marshal.PtrToStringAnsi(param9);

还有一种更简单的字符串使用方法,这要归功于下面的答案:

[DllImport("mydll.dll")]
public static extern IntPtr foo(
    string in1,
    string in2,
    string in3,
    string in4,
    string in5,
    string in6,
    string in7,
    string in8,
    StringBuilder result1,
    StringBuilder result2);

然后:

StringBuilder resultA = new StringBuilder(512);
StringBuilder resultB = new StringBuilder(512);
foo("test", "test", "test", "test", "test", "test", "test", "test", resultA, resultB);

打印:

Console.WriteLine(resultA.ToString());

它现在看起来好多了,而且现在确实有效,谢谢大家!打开50个谷歌搜索标签很容易让人感到困惑。

如何从C#的char*向非托管C++DLL传递和接收数据

假设您有以下c声明

extern "C" __declspec(dllexport) {
    void foo(char * input, char * output);
}

我将定义以下C#定义:

[DllImport("mydll.dll", EntryPoint="foo")]
public static extern void Foo(string input, StringBuilder output);

通话内容如下:

string input = "input";
var output = new StringBuilder(512);
Foo(input, output);

如果可能的话,尽量避免使用不安全的代码。