You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# DLL中ref byte[]参数的C++正确传递方法及调用排查

问题分析:C++调用C# DLL中ref byte[]参数的正确方式

你的当前调用完全不正确,这正是运行异常的根源。咱们一步步拆解问题,再给出正确的实现方式:

为什么原代码会崩溃?

你这里的ptr是一个初始化为0的unsigned char*,然后强制转换成SAFEARRAY**传递给WriteSingleCoils。但C#的ref byte[]在COM互操作中对应的是指向SAFEARRAY指针的指针,而不是普通字节指针。直接传空指针的地址,会让C#尝试往内存地址0写入数据——这是非法内存访问,必然导致崩溃。

正确的传递方式

C#的ref byte[]意味着:方法会创建一个新的字节数组(或者修改传入的数组),并把这个数组的COM表示(也就是SAFEARRAY)赋值给你传入的指针。所以你需要做这几步:

  1. 声明一个SAFEARRAY*变量,初始化为nullptr;
  2. 传递这个变量的地址(也就是SAFEARRAY**类型)给方法;
  3. 方法返回后,处理这个SAFEARRAY里的数据,最后记得释放它避免内存泄漏。

修改后的代码示例:

// 用智能指针管理IMaster实例,比手动new/delete更安全
IMasterPtr pIMast(__uuidof(Master)); 

// 声明SAFEARRAY指针,初始化为空
SAFEARRAY* pResult = nullptr;

// 传递&pResult(SAFEARRAY**类型),匹配C#的ref byte[]
// 注意:布尔参数用COM规范的VARIANT_TRUE/VARIANT_FALSE,避免类型兼容问题
pIMast->WriteSingleCoils(1, 0, 144, VARIANT_TRUE, &pResult);

// 处理返回的结果
if (pResult != nullptr) {
    unsigned char* pData = nullptr;
    // 锁定SAFEARRAY获取数据指针
    HRESULT hr = SafeArrayAccessData(pResult, (void**)&pData);
    if (SUCCEEDED(hr)) {
        // 获取数组的上下界,计算长度
        long lowerBound, upperBound;
        SafeArrayGetLBound(pResult, 1, &lowerBound);
        SafeArrayGetUBound(pResult, 1, &upperBound);
        long arrayLength = upperBound - lowerBound + 1;

        // 这里可以使用pData里的数据,比如复制到你自己的缓冲区
        // 例如:memcpy(yourBuffer, pData, arrayLength);

        // 解锁SAFEARRAY
        SafeArrayUnaccessData(pResult);
    }
    // 释放SAFEARRAY,避免内存泄漏
    SafeArrayDestroy(pResult);
}

关键要点总结

  • ref byte[]在COM互操作中映射为SAFEARRAY**,因为数组在COM中用SAFEARRAY表示,ref要求传递指针的指针,让被调用方可以修改指针指向的对象。
  • 绝对不能把普通的unsigned char*强制转换成SAFEARRAY**,两者的内存结构完全不同,类型不匹配。
  • 使用完SAFEARRAY后必须调用SafeArrayDestroy释放,否则会造成内存泄漏。
  • 布尔参数尽量使用COM规范的VARIANT_TRUE/VARIANT_FALSE,而不是C++原生的true/false,避免跨语言类型兼容问题。

内容的提问来源于stack exchange,提问作者Hemant salwan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:36:54