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

如何向wchar_t*指针参数写入文本(C++导出DLL供Dart调用)

问题说明

需要将C实现的功能打包为DLL导出供Dart调用,核心需求是实现带wchar_t*指针参数的函数,通过该出参向调用方返回文本内容。因不熟悉C指针语法,自行编写的代码存在运行错误,未找到可行解决方案。
原有错误实现逻辑为枚举系统音频设备,将设备信息拼接为宽字符串后写入传入的指针缓冲区。

核心错误点
  • 缓冲区长度参数传参错误:wcscpy_s的第二个参数要求传入缓冲区可容纳的wchar_t元素个数,而测试代码中传入的sizeof(output)是缓冲区的总字节数。Windows平台下单个wchar_t占2字节,1000个元素的数组sizeof计算结果为2000,会导致函数误认为缓冲区长度是实际的2倍,写入时触发内存越界崩溃。
  • 宽字符串输出方式错误:cout是窄字符流,无法正确输出wchar_t*类型的宽字符串,会输出乱码或地址值,宽字符需要使用wcout输出。
  • DLL导出配置缺失:给Dart调用的导出函数必须加extern "C"标识,否则C++编译器会对函数名做名称修饰,Dart侧无法通过原函数名找到导出入口。
  • 冗余写法:listOutput += info.c_str()属于多余操作,std::wstring已经重载了对同类型字符串的拼接运算符,直接传入info对象即可。
修正后代码
#include <iostream>
#include <vector>
#include <string>
// 此处替换为你项目中音频枚举、DeviceProps定义所需的头文件

// 固定加extern "C" 避免C++名称修饰,保证DLL导出函数名和代码中定义一致
extern "C" __declspec(dllexport)
void getAudioDevices(wchar_t* output, int outBufferCharCount)
{
    std::vector<DeviceProps> result = EnumAudioDevices(eRender);
    std::wstring listOutput;
    if (!result.empty())
    {
        for (const auto& device : result)
        {
            std::wstring info;
            info += device.name;    // PCWSTR类型可直接拼接
            info += L"\n";
            info += device.iconInfo;// PCWSTR类型可直接拼接
            info += L"\n";
            info += device.id;      // LPWSTR类型可直接拼接
            info += L"\n";
            info += device.isActive ? L"true" : L"false";
            info += L"\n[][][][]\n";
            listOutput += info;
        }
    }
    // 安全拷贝字符串到传入的缓冲区,自动处理截断和末尾终止符
    wcscpy_s(output, outBufferCharCount, listOutput.c_str());
}

// 本地测试入口,编译DLL时可通过宏隔离不参与编译
#ifdef LOCAL_DEBUG
int wmain(int argc, WCHAR* argv[])
{
    const int bufCharLen = 1000;
    WCHAR output[bufCharLen];
    // 传入的长度参数为wchar_t元素个数,不是字节数
    getAudioDevices(output, bufCharLen);
    // 宽字符串用wcout输出
    wcout << output << std::endl;
    return 0;
}
#endif
Dart FFI调用注意事项
  • Windows平台下wchar_t对应UTF-16编码,Dart侧FFI类型映射为Pointer<Utf16>。
  • 分配缓冲区时按单个字符2字节计算总内存大小,第二个参数传入分配的缓冲区可容纳的字符个数,和C++侧参数语义保持一致。
  • 调用完成后通过Utf16.fromUtf16()方法将指针内容转为Dart原生String,使用完成后及时释放手动分配的缓冲区内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:00:58