将 SWIG 与 C++ 的 std::map 一起使用时,Java 没有迭代器
Posted
技术标签:
【中文标题】将 SWIG 与 C++ 的 std::map 一起使用时,Java 没有迭代器【英文标题】:No iterator for Java when using SWIG with C++'s std::map 【发布时间】:2012-02-27 13:31:44 【问题描述】:我已经在 C++ 中实现了一个带有 std::map
的类,并使用 SWIG 创建了从 Java 调用的接口。但是,没有迭代器对象允许我遍历 SWIG 包装的 std::map
中的条目。有谁知道如何创建迭代器?
【问题讨论】:
您需要准确说明不是“所有”条目的含义。有什么具体的,比如最后一项丢失了吗?分享一些代码,向我们展示您是如何进行互操作的? 抱歉,确切地说,我根本无法执行任何迭代。 快速谷歌搜索发现:chadretz.wordpress.com/2009/11/27/…也许有帮助 【参考方案1】:为了能够在 Java 中迭代对象,它需要实现 Iterable
。这又需要一个名为iterator()
的成员函数,它返回Iterator
的合适实现。
从您的问题来看,您是否在地图中使用了哪些类型以及您是否希望能够迭代对(就像在 C++ 中那样)、键或值,还不是很清楚。三种变体的解决方案基本相似,我在下面的示例中选择了值。
首先,我用来测试的 SWIG 接口文件的序言:
%module test
%include "std_string.i"
%include "std_map.i"
为了实现可迭代映射,我在 SWIG 接口文件中声明、定义和包装了另一个类。这个类,MapIterator
为我们实现了Iterator
接口。它是 Java 和封装的 C++ 的混合体,其中一个比另一个更容易编写。首先是一些 Java,一个类型映射,它给出了它实现的接口,然后是 Iterable
接口所需的三个方法中的两个,作为一个类型映射给出:
%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
自己的@987654332 表示@)。
%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>;
这可能更通用,例如使用宏来隐藏地图的类型,这样如果您有多个地图,只需像使用%template
一样为适当的地图“调用”宏。
原始类型的映射也有一点复杂 - 您需要安排 Java 端使用 Double
/Integer
而不是 double
/int
(我相信自动装箱是术语) ,除非您已经决定包装对,在这种情况下,您可以使用原始成员制作一对。
【讨论】:
以上是关于将 SWIG 与 C++ 的 std::map 一起使用时,Java 没有迭代器的主要内容,如果未能解决你的问题,请参考以下文章
SWIG:使用带有 shared_ptr 的 std::map 访问器?
C++ 将预先保留的哈希映射(std::unordered_map)与整数键和连续数据数组(std::vector)进行比较
如何使用 SWIG 将 C++ 数组转换为 Python 列表?