Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C DLL中的PInvoke char*在C#中作为字符串处理。空字符问题_C#_C_String_Pinvoke_Dllimport - Fatal编程技术网

C DLL中的PInvoke char*在C#中作为字符串处理。空字符问题

C DLL中的PInvoke char*在C#中作为字符串处理。空字符问题,c#,c,string,pinvoke,dllimport,C#,C,String,Pinvoke,Dllimport,C DLL中的函数如下所示: int my_Funct(char* input, char* output); byte[] input = Encoding.Default.GetBytes(inputString); 我必须从C#app中调用它。我是这样做的: ...DllImport stuff... public static extern int my_Funct(string input, string output); 输入字符串被完美地传输到DLL(我有明显的证据)。虽然函

C DLL中的函数如下所示:

int my_Funct(char* input, char* output);
byte[] input = Encoding.Default.GetBytes(inputString);
我必须从C#app中调用它。我是这样做的:

...DllImport stuff...
public static extern int my_Funct(string input, string output);
输入字符串被完美地传输到DLL(我有明显的证据)。虽然函数填写的输出是错误的。我有六个数据,比如:

3F-D9-00-01
但不幸的是,两个零之后的所有内容都被删除了,只有前两个字节进入我的C#app。它之所以会发生,是因为(我猜)它将其视为空字符,并将其作为字符串的结尾

你知道我怎样才能摆脱它吗?我试图将其指定为out IntPtr而不是字符串,但我不知道以后如何处理它。 我试着做以下事情:

 byte[] b1 = new byte[2];
 Marshal.Copy(output,b1,0,2);
2通常应为字节数组的长度。但是我会遇到各种各样的错误:比如“请求的范围超出了数组的末尾”或者“试图读取或写入受保护的内存…”


非常感谢您的帮助。

您对输出字符串的编组不正确。将数据从托管传递到本机时,在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();

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

public static extern int my_Funct(
    [In] byte[] input, 
    [Out] byte[] output
);
这与您的C声明相匹配

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

int my_Funct(char* input, char* output);
byte[] input = Encoding.Default.GetBytes(inputString);
如果您想使用不同的编码,那么很明显如何做到这一点

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

byte[] output = new byte[input.Length];
不知何故,你的C函数必须知道数组的长度。我会把那部分留给你的

然后可以调用该函数

int retval = my_Funct(input, output);
然后再次使用
编码
类将输出数组转换回C#字符串

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

(1) C#字符串比字符宽;它们的宽度是2个字符,而不是1个字符。(2) 此函数返回的char*没有必要的附加结构才能成为有效的C#字符串(即使其宽度正确)。您需要阅读COM Interop和P/Invoke以了解如何执行此操作。这样做,如果您对该材料有任何疑问,请返回。pinvoke marshaller仅支持C字符串。当0后面有重要的字节时,它显然不是C字符串。然后是一个字节[]。但由于出现了严重的挂断,因此没有人能够计算出有多少字节是相关的。这个函数也很难从C代码中使用,当你pinvoke的时候,它也不会变得更好。你最好把它修好。如果长度是可预测的,请使用MarshalAs.SizeConst。