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

C++类型转C++/CLI:包装原生C++库供C#调用时类型转换报错如何解决

C++/CLI 包装原生C++接口类型转换解决方案

报错原因说明

你遇到的String^转wchar_t*不支持的报错,核心原因是msclr::interop::marshal_context的marshal_as方法将托管字符串转为宽字符指针时,默认返回const wchar_t*类型,指向由context管理的只读内存块,不允许直接赋值给非const的wchar_t*,所以换成const wchar_t*就可以正常编译。
同时你写的string_to_wchar函数存在严重野指针问题:context被delete后,它管理的所有转换后的非托管内存都会被释放,返回的wchar_t*是无效指针,调用原生函数时大概率触发崩溃。

三类原生指针的正确转换方式

1. void* 和 IntPtr 转换

你当前的转换逻辑完全正确:

  • 原生C的void*对应C/CLI的IntPtr托管类型
  • 传入原生函数时调用IntPtr::ToPointer()即可拿到原生void*指针,只需确保传入的IntPtr指向的原生资源未提前释放即可

2. wchar_t* 和 String^ 转换

需根据原生函数是否修改Feature参数分两种情况处理:

情况1:原生函数不会修改Feature内容(绝大多数场景)

直接在当前函数作用域内使用栈分配的marshal_context,保证context生命周期覆盖原生函数调用全程,对返回的const指针做强转即可:

int CppCliFunc(IntPtr Handle, String^ Feature, long long% Value) {
    marshal_context context; // 栈分配自动释放,无需手动管理
    const wchar_t* unmanagedFeature = context.marshal_as<const wchar_t*>(Feature);
    return ::CppFunc(Handle.ToPointer(), const_cast<wchar_t*>(unmanagedFeature), &Value);
}

情况2:原生函数确实会修改Feature内容

需要手动分配非托管内存,拷贝字符串后传入,调用完成后释放内存:

int CppCliFunc(IntPtr Handle, String^ Feature, long long% Value) {
    int strLen = Feature->Length + 1;
    wchar_t* unmanagedFeature = new wchar_t[strLen];
    // 托管字符串拷贝到非托管内存
    Marshal::Copy(Feature->ToCharArray(), 0, IntPtr(unmanagedFeature), strLen);
    
    int ret = ::CppFunc(Handle.ToPointer(), unmanagedFeature, &Value);
    
    // 若需要把修改后的字符串传回托管侧,可在此处把unmanagedFeature转为String^返回
    delete[] unmanagedFeature;
    return ret;
}

3. long long* 对应托管类型转换

你当前的写法不符合托管代码调用习惯,原生的long long*(单值输出场景)对应C++/CLI的long long%跟踪引用,C#侧会自动识别为out long long参数:

  • 如果是输入参数,直接用long long值类型即可,调用原生函数时取地址传入
  • 如果是输出/输入输出参数,用long long%,调用原生函数时取&Value即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 22:54:05