使用StringBuilder进行PInvoke访问冲突

时间:2016-10-18 15:02:48

标签: c# c pinvoke

我目前正在测试一些PInvoke的东西并写了一个简短的C函数来尝试一些不同的东西。我成功地设法通过了Ints并返回了一个附加内容,但是在字符串方面我遇到了一些麻烦。

这是C函数:

__declspec(dllexport) int test(char *str, int slen){
    for(int i = 0; i < slen; i++){
        str[i] = 'a';
    }
    return slen;
}

这是C#函数声明和用法:

[DllImport("solver.dll", CharSet = CharSet.Ansi ,CallingConvention = CallingConvention.Cdecl)]
public static extern int test(StringBuilder sol, int len);

StringBuilder sol = new StringBuilder(15);
int ret = test(sol, sol.Capacity);
string str = sol.ToString();

我在一天的大部分时间里一直在研究这个问题,我看过几篇关于简单地传递一个StringBuilder的帖子,把它填充到C端,当函数完成时它应该是可访问的。但是我目前在C代码中收到一个AccessViolation错误,好像没有分配内存,但我肯定会用new StringBuilder(15)分配内存

如果我在C代码中分配一块内存并传递它,那么C函数肯定有效。 有什么我想念的吗?

1 个答案:

答案 0 :(得分:1)

听起来你错过NUL终止字符串缓冲区。

您可能希望像这样更新代码:

for (int i = 0; i < (slen-1); i++) {
    str[i] = 'a';
}
str[slen-1] = '\0'; // Add a NUL-terminator

请注意,在这种情况下,我假设调用者传递的缓冲区长度为长度,包括 NUL终结符的空间。

(其他约定也是可能的,例如假设调用者传递的长度排除了NUL终结符;重要的是接口文档的 clear 。)

我还想补充一点,这些导出函数的常用调用约定是__stdcall而不是__cdecl(尽管这与您的问题无关)。

相关问题