在 C# 和 C DLL 之间传递字符串:一个最小示例
问题陈述
尽管按照看似简单的方法,通过互操作在 C# 和 C DLL 之间传递字符串会导致System.AccessViolationException。两种语言的代码看起来都是正确的,导致人们对问题的根本原因感到困惑。
C 代码
C 代码定义了一个函数 concat,用于连接两个字符串并返回结果。此函数使用 __declspec(dllexport) 标记为导出到 DLL。
extern "C" { string concat(string a, string b){ return a + b; } }
C# 代码
在 C# 中,代码使用 DllImport 导入 concat 函数。 CallingConvention 设置为 Cdecl 以匹配 C 约定。
[DllImport("*****.dll", CallingConvention = CallingConvention.Cdecl)] static extern string concat(string a, string b);
异常与分析
在 C# 中调用 concat("a", "b") 会抛出异常System.AccessViolationException。此异常表明本机代码中发生了无效的内存访问。
解决方案:互操作兼容类型
问题的罪魁祸首在于使用 C std ::跨越互操作边界的字符串。 C# 无法直接创建或处理 std::string 对象。相反,必须采用互操作兼容的类型来进行数据交换。
互操作友好的数据类型
合适的互操作类型包括用于传递字符串的空终止字符数组C# 到 C .将字符串从 C 传递到 C# 时,可以使用 StringBuilder,调用者分配缓冲区,被调用者写入缓冲区。
修改代码
在 C 中, concat 函数可以使用 char* 和 int 参数声明,以接收缓冲区及其长度。
extern "C" { void concat(char *str, int len) { // Concatenate strings and write to buffer } }
中C# 可以利用 StringBuilder。
[DllImport("...", CallingConvention = CallingConvention.Cdecl)] static extern void concat(StringBuilder str, int len); .... StringBuilder sb = new StringBuilder(10); concat(sb, sb.Capacity);
通过使用互操作兼容的字符串类型,可以有效地促进 C# 和 C DLL 之间的字符串交换。
以上是在 C# 和 C DLL 之间传递字符串时如何避免 System.AccessViolationException?的详细内容。更多信息请关注PHP中文网其他相关文章!