如何用SWIG 4.0.2将C# string[]传入C/C++结构体字符数组成员
用SWIG 4.0.2实现C# string[]给C++结构体字符串数组赋值的方案
1. 编写SWIG接口文件
创建接口文件(比如MarketData.i),通过类型映射和结构体扩展实现C#与C++的类型转换,代码如下:
%module MarketData %include "cstring.i" // 声明与C/C++端一致的基础类型 typedef char TDACharType; typedef int TDAIntType; typedef char TDAStringType[256]; // 为MarketTrcode生成C#属性的getter,将C++二维char数组转为string[] %typemap(csgetter) TDAStringType CMarketReqMarketDataField::MarketTrcode[20] { get { string[] result = new string[20]; for (int i = 0; i < 20; i++) { result[i] = GetMarketTrcode(i); } return result; } } // 为MarketTrcode生成C#属性的setter,将string[]转为C++二维char数组 %typemap(cssetter) TDAStringType CMarketReqMarketDataField::MarketTrcode[20] { set { if (value == null) { throw new ArgumentNullException(nameof(value)); } if (value.Length > 20) { throw new ArgumentException("MarketTrcode数组长度不能超过20", nameof(value)); } // 赋值有效元素 for (int i = 0; i < value.Length; i++) { SetMarketTrcode(i, value[i] ?? ""); } // 清空剩余元素 for (int i = value.Length; i < 20; i++) { SetMarketTrcode(i, ""); } // 自动更新有效元素数量 MarketCount = value.Length; } } // 扩展结构体,添加访问数组元素的底层方法 %extend CMarketReqMarketDataField { const char* GetMarketTrcode(int index) { if (index < 0 || index >= 20) { return ""; } return $self->MarketTrcode[index]; } void SetMarketTrcode(int index, const char* str) { if (index < 0 || index >= 20) { return; } memset($self->MarketTrcode[index], 0, sizeof(TDAStringType)); if (str) { strncpy($self->MarketTrcode[index], str, sizeof(TDAStringType) - 1); } } } // 定义目标结构体 struct CMarketReqMarketDataField { TDACharType MarketType; TDACharType SubscMode; TDAIntType MarketCount; TDAStringType MarketTrcode[20]; TDAStringType ErrorDescription; };
2. 生成SWIG包装代码
执行以下命令编译接口文件,生成C#包装类和C++中间代码:
swig -csharp -c++ MarketData.i
生成文件包括:
MarketData.cs:C#端的结构体包装类MarketDataPINVOKE.cs:C#调用C++的PINVOKE桥接代码MarketData_wrap.cxx:C++端的包装实现
3. 编译C++动态链接库
将MarketData_wrap.cxx与你的C++业务代码一起编译为动态链接库(DLL),确保编译时链接必要依赖。
4. C#端调用示例
在C#项目中引用生成的C#类文件,直接通过属性赋值:
// 创建结构体实例 var marketReq = new CMarketReqMarketDataField(); // 用string[]为MarketTrcode赋值 marketReq.MarketTrcode = new string[] { "TR001", "TR002", "TR003" }; // 此时MarketCount会自动设置为3,对应有效元素数量 Console.WriteLine($"有效市场代码数量:{marketReq.MarketCount}");
关键注意事项
- 接口文件中的基础类型必须与C/C++端的typedef完全一致,否则会出现类型不匹配问题。
SetMarketTrcode方法中用strncpy限制长度为255,配合memset清空数组,避免缓冲区溢出。- C# setter中处理了空数组、长度超限的情况,防止非法输入导致C++端崩溃。
内容的提问来源于stack exchange,提问作者AndySun
相关产品推荐
相关产品推荐

