简体   繁体   English

在单元测试中使用StringBuilder P调用

[英]PInvoking with StringBuilder in a Unit Test

I have a C DLL I am PInvoking. 我有一个正在调用的C DLL。 The main goal is to get back a GUID string of 39 characters, such as abcd-abcd-abcd-abcd-abcd-abcd-abcd-abcd . 主要目标是取回39个字符的GUID字符串,例如abcd-abcd-abcd-abcd-abcd-abcd-abcd-abcd

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: 我首先调用一个方法来获取此字符串的大小,该字符串的大小预计为39个字符,然后调用另一个函数,将其传递给容量为39的StringBuilder

[DllImport("test.dll")]
public static extern int get_size();

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

My code looks something like this: 我的代码如下所示:

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

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-abcd

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 当我使用完全相同的代码从单元测试中调用此abcd-abcd-abcd-abcd-abcd-abcd-abcd-abcdq ,我得到以下结果: abcd-abcd-abcd-abcd-abcd-abcd-abcd-abcdq

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? 注意最后的q ,添加了额外的字符,以及通过调试单元测试,我可以验证StringBuilder对象的容量在调用get_string 之后已显着增加到42(尽管已初始化为39)为什么会这样? Is this normal? 这正常吗? Am I doing something wrong? 难道我做错了什么? Why only in the unit tests? 为什么只在单元测试中?

The C implementation is something like this: 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));
}

This required a few fixes. 这需要一些修复。

The function signature needed to change: 需要更改的功能签名:

[DllImport("test.dll")]
public static extern int get_size();

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

The C implementation needed to change: 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);
}

The C# call needed to change: 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());

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. 有关C的新手的说明...如果您不使用char ,并且使用的是wchar_t或其他方式,以及字符串长度的计算方法,则需要将缓冲区大小乘以sizeof(wchar_t)相反,在执行类似memset操作时,因为字符串中的字符数和字符串中的字节数之间存在很大差异。 I just happen to know what sizeof(char) is 1 so I've omitted this from the implementation to save code. 我只是碰巧知道sizeof(char)是1,所以我从实现中省略了此代码以保存代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM