加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

使用带有C的std :: map的SWIG时没有Java的迭代器

发布时间:2020-12-16 03:45:12 所属栏目:百科 来源:网络整理
导读:我在C中实现了一个带有std :: map的类,并使用SWIG创建了从 Java调用的接口.但是没有迭代器对象允许我遍历SWIG包装的std :: map中的条目.有谁知道如何创建迭代器? 解决方法 为了能够在Java中迭代Object,它需要实现Iterable.这又需要一个名为iterator()的成员
我在C中实现了一个带有std :: map的类,并使用SWIG创建了从 Java调用的接口.但是没有迭代器对象允许我遍历SWIG包装的std :: map中的条目.有谁知道如何创建迭代器?

解决方法

为了能够在Java中迭代Object,它需要实现Iterable.这又需要一个名为iterator()的成员函数,它返回一个合适的Iterator实现.

从你的问题来看,你不清楚你在地图中使用了什么类型,以及你是否希望能够迭代对(如在C中),键或值.三种变体的解决方案基本相似,下面我的例子选择了值.

首先,我用来测试这个SWIG接口文件的前导码:

%module test

%include "std_string.i"
%include "std_map.i"

为了实现可迭代的映射,我已经声明,定义并包装了SWIG接口文件中的另一个类.这个类,MapIterator为我们实现了Iterator接口.它是Java和包装C的混合体,其中一个比另一个更容易编写.首先是一些Java,一个类型映射,它给它实现的接口,然后是Iterable接口所需的三个方法中的两个,作为一个typemap给出:

%typemap(javainterfaces) MapIterator "java.util.Iterator<String>"
%typemap(javacode) MapIterator %{
  public void remove() throws UnsupportedOperationException {
    throw new UnsupportedOperationException();
  }

  public String next() throws java.util.NoSuchElementException {
    if (!hasNext()) {
      throw new java.util.NoSuchElementException();
    }

    return nextImpl();
  }
%}

然后我们提供MapIterator的C部分,它具有除了抛出next()部分的异常以及迭代器所需的状态(用std :: map自己的const_iterator表示)之外的所有私有实现.

%javamethodmodifiers MapIterator::nextImpl "private";
%inline %{
  struct MapIterator {
    typedef std::map<int,std::string> map_t;
    MapIterator(const map_t& m) : it(m.begin()),map(m) {}
    bool hasNext() const {
      return it != map.end();
    }

    const std::string& nextImpl() {
      const std::pair<int,std::string>& ret = *it++;
      return ret.second;
    }
  private:
    map_t::const_iterator it;
    const map_t& map;    
  };
%}

最后我们需要告诉SWIG我们正在包装的std :: map实现了Iterable接口并提供了一个额外的成员函数,用于包装std :: map,它返回我们刚写的MapIterator类的新实例:

%typemap(javainterfaces) std::map<int,std::string> "Iterable<String>"

%newobject std::map<int,std::string>::iterator() const;
%extend std::map<int,std::string> {
  MapIterator *iterator() const {
    return new MapIterator(*$self);
  }
}

%template(MyMap) std::map<int,std::string>;

这可能是更通用的,例如用宏来隐藏地图的类型,这样如果你有多个地图,那么就像使用%模板一样“调用”适当地图的宏.

原始类型的映射也有一点点复杂 – 你需要安排Java端使用Double / Integer而不是double / int(我相信是自动装箱这个术语),除非你决定在这种情况下包装对你可以与原始成员配对.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读