To be able to iterate over an object in Java, it needs to implement Iterable . This, in turn, requires a member function called iterator() , which returns a suitable implementation of Iterator .
From your question it is not clear what types you use on the map, and whether you want to be able to iterate over pairs (as in C ++), keys or values. The solutions for the three options are essentially the same, my example below took the values.
First of all, the preamble for the SWIG interface file that I used for testing:
%module test %include "std_string.i" %include "std_map.i"
To implement an iterable map, I declared, defined, and wrapped another class in the SWIG interface file. This MapIterator class implements the Iterator interface for us. This is a mixture of both Java and wrapped C ++, where one was easier than the other to write. Firstly, some Java, a generic map that provides the interface that it implements, and then two of the three methods required for the Iterable interface, defined as a map:
%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(); } %}
Then we supply the C ++ part of MapIterator , which has a private implementation of all but the exception, which throws the next() and the state needed for the iterator (expressed in terms of std::map own 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; }; %}
Finally, we need to tell SWIG that std::map we wrap the Iterable interface and provide an additional member function for wrapping std::map , which returns a new instance of the MapIterator class, which we simply wrote:
%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>;
This may be more common with macros, for example, to hide map types, so if you have multiple cards, it is just a matter of βinvokingβ the macro for the respective cards, as is the case with %template .
There is also a slight complication with cards of primitive types - you will need to persuade the Java server to use Double / Integer instead of Double / int (autoboxing, I think, is a term), if you did not decide to wrap pairs already in this case, you could create a pair with primitive members.