在单元测试中使用StringBuilder P调用 [英] PInvoking with StringBuilder in a Unit Test
问题描述
我有一个正在调用的C DLL.主要目标是取回39个字符的GUID字符串,例如abcd-abcd-abcd-abcd-abcd-abcd-abcd-abcd
.
I have a C DLL I am PInvoking. The main goal is to get back a GUID string of 39 characters, such as abcd-abcd-abcd-abcd-abcd-abcd-abcd-abcd
.
我首先调用一个方法来获取此字符串的大小,该字符串的大小预计为39个字符,然后调用另一个函数,将其传递为容量为39的StringBuilder
:
I first call one method to get the size of this string, which I expect to be 39 characters, and then I call another function passing it a StringBuilder
with a capacity of 39:
[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
When I call this in a console application, I get back this result: abcd-abcd-abcd-abcd-abcd-abcd-abcd-abcd
当我使用完全相同的代码从单元测试中调用此代码时,我会得到以下结果:abcd-abcd-abcd-abcd-abcd-abcd-abcd-abcdq
When I call this from a unit test with the exact same code, I get back this result: abcd-abcd-abcd-abcd-abcd-abcd-abcd-abcdq
请注意最后的q
,添加了额外的字符,以及通过调试单元测试,我可以验证StringBuilder
对象的容量已显着增加,直至达到42 .对get_string
的调用,尽管已被初始化为39的容量.为什么会发生这种情况?这正常吗?难道我做错了什么?为什么只在单元测试中?
Note the q
on the end, the extra character that is added, and that from debugging the unit test I can verify that the capacity of the StringBuilder
object has increased significantly up to 42 after the call to get_string
despite being initialized with a capacity of 39. Why is this happening? Is this normal? Am I doing something wrong? Why only in the unit tests?
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
的方法,或者您使用的是字符串长度计算方法,则需要乘以像memset
这样的操作时,缓冲区大小由sizeof(wchar_t)
代替,因为字符串中的字符数和字符串中的字节数之间存在很大差异.我只是碰巧知道sizeof(char)
是1,所以我在实现中省略了此代码以保存代码.
A note to rookies of C...if you're not using char
, and you're using something like wchar_t
or otherwise, along with your string length calculation methods, you'll need to multiply your buffer sizes by sizeof(wchar_t)
instead when doing operations like memset
, since there's a big difference between number of characters in a string and number of bytes in a string. I just happen to know what sizeof(char)
is 1 so I've omitted this from the implementation to save code.
这篇关于在单元测试中使用StringBuilder P调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!