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

使用SWIG时如何让csinterface_derived生效实现C# IEnumerable接口

问题:为SWIG导出的C++ Container模板类添加C# IEnumerable接口

C++类继承结构

class Base{  
public:
  virtual ~Base() = default; 
};
template<class T> class Container : public Base{ 
public:
  ~Container () override = default;
  // 其他实现代码
};

需求与问题

已将Base类导出到C#,希望让Container<int>对应的C#类实现IEnumerable<int>接口。尝试使用SWIG的csinterface_derived类型映射,但以下写法无效(调换两行顺序后IEnumerable接口仍缺失):

%typemap(csinterface_derived) Container<int>  “IEnumerable<int>";
%template (ContainerOfInt) Container<int>;

解决方案

1. 修复核心语法错误

你代码中使用的中文引号(“/”)是映射失效的直接原因,必须替换为英文双引号(")。

2. 规范typemap与模板声明顺序

SWIG要求类型映射必须先于模板实例化声明,确保处理模板时能正确应用映射规则:

// 先定义类型映射(使用英文引号)
%typemap(csinterface_derived) Container<int> "IEnumerable<int>";
// 再声明模板实例
%template(ContainerOfInt) Container<int>;

3. 泛型模板的通用映射(可选)

如果需要为所有Container<T>实例自动添加IEnumerable<T>接口,可使用模板参数匹配的typemap:

%typemap(csinterface_derived) Container<T> "IEnumerable<T>";
%template(ContainerOfInt) Container<int>;
%template(ContainerOfString) Container<std::string>;

4. 补充接口实现(关键)

仅添加接口声明无法通过C#编译,必须为IEnumerable<T>实现GetEnumerator()方法。假设C++的Container类提供begin()/end()迭代器,可通过SWIG的%extend扩展功能实现:

// 为Container<T>添加GetEnumerator方法映射
%extend Container<T> {
    System::Collections::Generic::IEnumerator<T>* GetEnumerator() {
        return new ContainerEnumerator<T>($self);
    }
}

// 辅助枚举器类(需在SWIG接口中定义)
template<class T>
class ContainerEnumerator : public System::Collections::Generic::IEnumerator<T> {
private:
    typename Container<T>::iterator it;
    typename Container<T>::iterator end;
    Container<T>* container;
public:
    ContainerEnumerator(Container<T>* c) : container(c) {
        it = c->begin();
        end = c->end();
    }

    bool MoveNext() override {
        return it != end;
    }

    void Reset() override {
        it = container->begin();
    }

    T Current::get() override {
        return *it++;
    }

    System::Object^ System::Collections::IEnumerator::Current::get() override {
        return *it++;
    }

    ~ContainerEnumerator() override = default;
};

验证

生成C#代码后,ContainerOfInt类的定义应包含如下内容:

public class ContainerOfInt : Base, IEnumerable<int> {
    // ... 自动生成的封装代码
    public IEnumerator<int> GetEnumerator() {
        // ... 映射后的枚举器实现
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 07:11:07