Calling the below code from python:
from f_p import form_p
print(form_p([1,2,3]))
Gives me below error
Error:
(<f_p.mapiv; proxy of <Swig Object of type 'std::map< char,int > *' at 0x7f09778fc270> >,)
How to resolve it? I am trying to create a wrapper for my cpp code in swig. Code files:
f_p.i:
%module f_p
#define SWIGPYTHON_BUILTIN
%{
#include "numpy/arrayobject.h"
#define SWIG_FILE_WITH_INIT /* To import_array() below */
#include "f_p.h"
%}
%include "std_map.i"
%import "std_deque.i"
// %include "numpy.i"
%import "std_vector.i"
#include <deque>
%template() std::vector<int>;
%template (map) std::map<char,int>;
%template(MapDeque) std::deque<std::map<char, int>>;
%include "f_p.h"
f_p.cpp:
#include <deque>
#include <iostream>
using namespace std;
#include <vector>
#include <map>
deque<map<char, int>> form_p(vector<int> inp_list)
{
map<char, int> my_map = {
{ 'A', 1 },
{ 'B', 2 },
{ 'C', 3 }
};
deque<map<char, int>> mydeque;
mydeque.push_back(my_map);
return mydeque;
}
f_p.h:
#ifndef F_P_H
#define f_P_H
#include <stdio.h>
#include <deque>
#include <map>
#include <vector>
/* Define function prototype */
std::deque<std::map<char, int>> form_p(std::vector<int> inp_list) ;
#endif
build.sh:
rm *.o f_p_wrap.cpp _f_p.so f_p.py
rm -rf __pycache__
g++ -O3 -march=native -fPIC -c f_p.cpp
swig -python -c++ -o f_p_wrap.cpp f_p.i
# Next, compile the wrapper code:
g++ -O3 -march=native -w -fPIC -c $(pkg-config --cflags --libs python3) -I /home/kriti/anaconda3/lib/python3.7/site-packages/numpy/core/include f_p.cpp f_p_wrap.cpp
g++ -std=c++11 -O3 -march=native -shared f_p.o f_p_wrap.o -o _f_p.so -lm
I ain't able to get the output. I don't know how to work with deque thing. for map and vector I am bale to produce the results but not with the deque and when there is char in map.
What you label as "Error" is the correct (or at least expected) result: the deque is translated to a Python tuple. To get to your map, simply access the first element, then access the map:
>>> from f_p import form_p
>>> print(form_p([1,2,3]))
(<f_p.map; proxy of <Swig Object of type 'std::map< char,int > *' at 0x7f16259a1c60> >,)
>>> d = form_p([1,2,3])
>>> len(d)
1
>>> d[0]
<f_p.map; proxy of <Swig Object of type 'std::map< char,int > *' at 0x7f16259aeb40> >
>>> m = d[0]
>>> len(m)
3
>>> m.keys()
['A', 'B', 'C']
>>> m['B']
2
>>> for m in d:
... print m.keys()
...
['A', 'B', 'C']
>>>
EDIT: follow-up based on comments. There is already an "out" typemap for std::deque
, which unfortunately matches more closely, so unless you specifiy std::deque<std::map<char, int>> form_p
completely (i.e. with the function name), it won't match, so the following example uses "ret" instead, to apply to all of your functions that return such deques. Add to f_p.i:
%typemap(ret) std::deque<std::map<char, int>> {
$result = PyTuple_New($1.size());
for (int i = 0; i < (int)$1.size(); ++i)
PyTuple_SetItem($result, i, swig::traits_from<std::map<char, int>>::asdict($1[i]));
}
This code creates a tuple (use PyList_New
and PyList_SetItem
if you prefer a python list), then loops over the entries in the deque and converts them to python dicts. The asdict
call is a generated python function which you can also use in python post-processing code in the .i if you prefer.
With that in place, the result is:
>>> from f_p import form_p
>>> print(form_p([1,2,3]))
({'A': 1, 'C': 3, 'B': 2},)
>>>