使用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
相关产品推荐
相关产品推荐

