DLL中的PInvoke char*在c#中被当作字符串处理.空字符的问题

本文关键字:处理 字符串 字符 问题 char PInvoke 中的 DLL | 更新日期: 2023-09-27 18:02:51

C DLL中的函数是这样的:

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

我必须从c# app中调用它。我用下面的方式来做:

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

输入字符串被完美地传输到DLL(我有可见的证据)。虽然函数填充的输出是错误的。我有十六进制数据在里面,像:

3F-D9-00-01

但不幸的是,在两个零之后的所有内容都被切断了,只有前两个字节来到我的c#应用程序。它发生了,因为(我猜)它将其视为空字符并将其作为字符串的结束。

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

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

2通常应为字节数组的长度。但我得到各种各样的错误:像"请求的范围延伸到数组的末尾。"或"试图读取或写入受保护的内存…"

谢谢你的帮助。

DLL中的PInvoke char*在c#中被当作字符串处理.空字符的问题

您对输出字符串的编组不正确。当将数据从托管传递到本机时,在p/invoke声明中使用string是合适的。但是当数据在另一个方向流动时,你不能使用它。相反,您需要使用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();

另一方面,如果这些参数中有空字符,则不能作为字符串封送。这是因为编组程序不会编组超过null的任何内容。相反,您需要将其封送为字节数组。

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

然后再使用Encoding类将输出数组转换回c#字符串。

string outputString = Encoding.Default.GetString(output);