将 SWIG 与 C++ 的 std::map 一起使用时没有 Java 迭代器
No iterator for Java when using SWIG with C++'s std::map
我在C++中用std::map
实现了一个类,并使用SWIG创建了接口,以便从Java调用。但是,没有一个迭代器对象允许我遍历SWIG封装的std::map
中的条目。有人知道如何创建迭代器吗?
为了能够在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
自己的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>;
这可能更通用,例如,使用宏来隐藏贴图的类型,这样,如果您有多个贴图,则只需要像使用%template
一样,为适当的贴图"调用"宏。
基元类型的映射也有一点复杂——您需要安排Java端使用Double
/Integer
,而不是double
/int
(我认为自动装箱是一个术语),除非您已经决定包装对,在这种情况下,您可以用基元成员组成一对。
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 如何在c++迭代器类型中包装std::chrono
- 集合上的输出迭代器:assign和increment迭代器
- Boost Spirit,获取迭代器内部语义动作
- 对于set上的循环-获取next元素迭代器
- 为什么output_editor Concept不需要output_e迭代器标记
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 使用迭代器时如何访问对象在向量中的位置?
- std::vector::迭代器是否可以合法地作为指针
- 跟随整数索引列表的自定义类迭代器
- 不明白迭代器,引用和指针失效,一个例子
- 我可以使用反向迭代器作为ForwardIt吗
- 从 QMap<K、T> 获取 Java 样式迭代器,而不指定 T、K
- 如何在类似java的c++中迭代器枚举
- 如何在Qt中使用java风格的迭代器而不是stl风格
- 将 SWIG 与 C++ 的 std::map 一起使用时没有 Java 迭代器
- C++ 迭代器模型与 Java 迭代器模型
- Java中的指针、矢量和迭代器