SWIG wrapping C++ for Python: translating a list o

2019-02-09 10:41发布

问题:

I would like to wrap a C++ function with SWIG which accepts a vector of STL strings as an input argument:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

void print_function(vector<string> strs) {
  for (unsigned int i=0; i < strs.size(); i++)
  cout << strs[i] << endl;
}

I want to wrap this into a Python function available in a module called `mymod':

/*mymod.i*/
%module mymod
%include "typemaps.i"
%include "std_string.i"
%include "std_vector.i"

%{
 #include "mymod.hpp"
%}

%include "mymod.hpp"

When I build this extension with

from distutils.core import setup, Extension

setup(name='mymod',
  version='0.1.0',
  description='test module',
  author='Craig',
  author_email='balh.org',
  packages=['mymod'],
  ext_modules=[Extension('mymod._mymod',
                         ['mymod/mymod.i'],
                         language='c++',
                         swig_opts=['-c++']),
                         ],
  )

and then import it and try to run it, I get this error:

Python 2.7.2 (default, Sep 19 2011, 11:18:13) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import mymod
>>> mymod.print_function("hello is seymour butts available".split())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: in method 'print_function', argument 1 of type 'std::vector<  std::string,std::allocator< std::string > >'
>>> 

I'm guessing this is saying that SWIG doesn't provide a default typemap for translating between a Python list of Python strings and a C++ STL vector of STL strings. I feel like this is something they might provide somewhere by default, but perhaps I don't know the right file to include. So how can I get this to work?

Thanks in advance!

回答1:

You need to tell SWIG that you want a vector string typemap. It does not magically guess all the different vector types that can exist.

This is at the link provided by Schollii:

//To wrap with SWIG, you might write the following:

%module example
%{
#include "example.h"
%}

%include "std_vector.i"
%include "std_string.i"

// Instantiate templates used by example
namespace std {
   %template(IntVector) vector<int>;
   %template(DoubleVector) vector<double>;
   %template(StringVector) vector<string>;
   %template(ConstCharVector) vector<const char*>;
}

// Include the header file with above prototypes
%include "example.h"


回答2:

SWIG does support passing a list to a function that takes a vector as value, or a const vector reference. The example at http://www.swig.org/Doc2.0/Library.html#Library_std_vector shows this, I can't see anything wrong with what you posted. Something else is wrong; DLL found by python was't the latest, the using namespace std in the header is confusing the SWIG wrapper code that does the type checking (note that "using namespace" statements in .hpp is a no-no in general as it pulls everything from std into global namespace), etc.