我目前正在测试一些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函数肯定有效。 有什么我想念的吗?
答案 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
(尽管这与您的问题无关)。