在unit testing中使用StringBuilder进行PInvoking

我有一个C DLL我是PInvoking。 主要目标是获取39个字符的GUID字符串,例如abcd-abcd-abcd-abcd-abcd-abcd-abcd-abcd

我首先调用一个方法来获取这个字符串的大小,我希望它是39个字符,然后我调用另一个函数传递一个容量为39的StringBuilder

 [DllImport("test.dll")] public static extern int get_size(); [DllImport("test.dll")] public static extern void get_string(StringBuilder result); 

我的代码看起来像这样:

 int size = get_size(); // Returns 40, because it includes the null terminating character. var result = new StringBuilder(size - 1); // Gives it a capacity of 39. Subtracting 1 here because this does not fancy that null terminator over the marshaling layer. get_string(result); Console.WriteLine(result.ToString()); 

当我在控制台应用程序中调用它时,我得到了这个结果: abcd-abcd-abcd-abcd-abcd-abcd-abcd-abcd

当我用完全相同的代码从unit testing中调用它时,我得到了这个结果: abcd-abcd-abcd-abcd-abcd-abcd-abcd-abcdq

注意最后的q ,添加的额外字符,以及调试unit testing后我可以validation尽管初始化容量为39,但在调用get_string 之后 StringBuilder对象的容量已大幅增加到42。为什么会这样? 这是正常的吗? 难道我做错了什么? 为什么只在unit testing?

C实现是这样的:

 static char *_result = NULL; // At some point result is initialized and set. int get_size() { if (_result != NULL) return strlen(_result) + 1; return 1; } void get_string(char *result) { if (result != NULL && _result != NULL) strncpy(result, _result, strlen(_result)); } 

这需要一些修复。

需要更改的函数签名:

 [DllImport("test.dll")] public static extern int get_size(); [DllImport("test.dll")] public static extern void get_string(int resultSize, StringBuilder result); 

C实现需要改变:

 static char *_result = NULL; // At some point result is initialized and set. int get_size() { if (_result != NULL) return strlen(_result) + 1; return 1; } void get_string(int resultSize, char *result) { memset(result, 0, resultSize); if (_result != NULL) strncpy(result, _result, resultSize); } 

需要更改C#调用:

 int resultSize = get_size(); var result = new StringBuilder(resultSize); // Needed to also include the null Terminator ("I'LL BE BACK" - ARNOLD). get_string(resultSize, result); Console.WriteLine(result.ToString()); 

给C新手的一个注释…如果你没有使用char ,并且你正在使用类似wchar_t或其他东西,以及你的字符串长度计算方法,你需要将你的缓冲区大小乘以sizeof(wchar_t)而是在进行像memset这样的操作时,因为字符串中的字符数和字符串中的字节数之间存在很大差异。 我碰巧知道sizeof(char)是1,所以我从实现中省略了这个以保存代码。