10

C DLL 中的函数如下所示:

int my_Funct(char* input, char* output);

我必须从 C# 应用程序调用它。我通过以下方式执行此操作:

...DllImport stuff...
public static extern int my_Funct(string input, string output);

输入字符串完美地传输到 DLL(我有明显的证据)。函数填写的输出虽然是错误的。我里面有六边形数据,比如:

3F-D9-00-01

但不幸的是,两个零之后的所有内容都被删除了,只有前两个字节进入我的 C# 应用程序。它发生了,因为(我猜)它被视为空字符并将其作为字符串的结尾。

知道我怎么能摆脱它?我试图将它指定为 out IntPtr 而不是字符串,但我不知道之后该怎么处理它。我试图做之后:

 byte[] b1 = new byte[2];
 Marshal.Copy(output,b1,0,2);

2 通常应该是字节数组的长度。但我得到了各种各样的错误:比如“请求的范围超出了数组的末尾。” 或“试图读取或写入受保护的内存......”

我很感激任何帮助。

4

1 回答 1

15

您对输出字符串的编组不正确。string在将数据从托管传递到本机时,在 p/invoke 声明中使用是合适的。但是当数据流向另一个方向时,您不能使用它。相反,您需要使用StringBuilder. 像这样:

[DllImport(...)]
public static extern int my_Funct(string input, StringBuilder output);

然后为输出分配内存:

StringBuilder output = new StringBuilder(256);
//256 is the capacity in characters - only you know how large a buffer is needed

然后你就可以调用这个函数了。

int retval = my_Funct(inputStr, output);
string outputStr = output.ToString();

另一方面,如果这些参数中包含空字符,则不能将其编组为字符串。那是因为编组器不会编组任何超过空值的东西。相反,您需要将其编组为字节数组。

public static extern int my_Funct(
    [In] byte[] input, 
    [Out] byte[] output
);

这与您的 C 声明相匹配。

然后假设 ANSI 编码将输入字符串转换为字节数组,如下所示:

byte[] input = Encoding.Default.GetBytes(inputString);

如果你想使用不同的编码,很明显如何做到这一点。

对于输出,您确实需要分配数组。假设它与输入的长度相同,您将执行以下操作:

byte[] output = new byte[input.Length];

不知何故,你的 C 函数必须知道数组的长度。我会把那一点留给你!

然后就可以调用函数了

int retval = my_Funct(input, output);

然后要将输出数组转换回 C# 字符串,请Encoding再次使用该类。

string outputString = Encoding.Default.GetString(output);
于 2013-03-07T15:21:33.140 回答