首页 >后端开发 >C++ >在 C# 和 C DLL 之间传递字符串时如何避免 System.AccessViolationException?

在 C# 和 C DLL 之间传递字符串时如何避免 System.AccessViolationException?

DDD
DDD原创
2025-01-02 19:01:38242浏览

How to Avoid System.AccessViolationException When Passing Strings Between C# and a C   DLL?

在 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中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn