Чтобы иметь возможность перебирать объект в 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();
}
%}
Затем мы поставляем часть C ++ для MapIterator
, которая имеет частную реализацию всего, кроме исключающей части next()
и состояния, необходимого для итератора (выраженного через собственные const_iterator
std::map
).
%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
(автобокс, как я полагаю, это термин), если только вы не решили обернуть пары уже, и в этом случае вы могли бы создать пару с примитивными членами.