C++宿主在Windows和Linux下如何向C#方法传递byte[]数组输出参数
跨平台C++宿主调用C# byte[]输出参数的封送方案
修正后的C#端实现
输出参数需要额外添加[Out]特性,同时用out修饰参数,告诉运行时将托管数组的内容反向拷贝到非托管内存,该规则在Windows和Linux的CoreCLR中通用:
public static string DoWork(int msgSize, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] out byte[] errMessage)
如果是C侧提前分配数组内存的场景,可以去掉out修饰,仅保留[In, Out]特性即可,这种模式下内存由C管理,避免跨语言内存释放的问题:
public static string DoWork(int msgSize, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] errMessage)
修正后的C++端实现
对应带out修饰的C#方法,函数指针的第二个参数需要改为二级指针,用来接收C#侧输出的数组地址:
// 对应out参数场景的函数指针定义 typedef char* (*doWork_ptr)(int dataSize, char** data);
调用示例:
int errBufSize = 1024; // 提前约定的数组最大长度 char* errBuf = nullptr; char* returnStr = doWorkInstance(errBufSize, &errBuf); // 调用完成后errBuf指向C#填充的字节数组,长度为errBufSize // 需提前约定内存释放规则,避免内存泄漏
对应C++预分配内存的场景,函数指针保持原一级指针定义即可:
typedef char* (*doWork_ptr)(int dataSize, char* data);
跨平台兼容注意事项
- 上述封送规则在Windows和Linux下完全一致,不需要额外做平台分支适配
- 返回的字符串默认编码在Windows下为ANSI、Linux下为UTF-8,如需统一编码可在C#方法返回值上添加
[return: MarshalAs(UnmanagedType.LPUTF8Str)]标记,避免乱码 - 优先选择C++侧预分配内存的方案,减少跨语言内存管理的复杂度
内容的提问来源于stack exchange,提问作者Jun Ge
相关产品推荐
相关产品推荐

