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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 15:50:38