10

I have a simple C++ class that contains a std::vector member and a member function that takes a std::vector as an argument that I am wrapping with SWIG and calling from Python. The example code is below.

After compiling it, I go into Python and do:

import test
t = test.Test()
a = [1, 2, 3]
b = t.times2(a) # works fine
t.data = a # fails!

The error message I get is:

TypeError: in method 'Test_data_set', argument 2 of type 'std::vector< double,std::allocator< double > > *'

I know that I can just do:

t.data = test.VectorDouble([1,2,3])

But I would like to know how to just use a Python list directly in the assignment, or at least understand why it doesn't work.


Here's the example code.

test.i:

%module test

%include "std_vector.i"

namespace std {
    %template(VectorDouble) vector<double>;
};

%{
#include "test.hh"
%}

%include "test.hh"

test.hh:

#include <vector>

class Test {
    public:
        std::vector<double> data;
        std::vector<double> times2(std::vector<double>);
};

test.cc:

#include "test.hh"

std::vector<double>
Test::times2(
    std::vector<double> a)
{
    for(int i = 0; i < a.size(); ++i) {
        a[i] *= 2.0;
    }
    return a;
}

makefile:

_test.so: test.cc test.hh test.i
    swig -python -c++ test.i
    g++ -fpic -shared -o _test.so test.cc test_wrap.cxx -I/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -L/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config/ -lpython2.7
Daniel Matz
  • 193
  • 1
  • 10

2 Answers2

5

Try using the %naturalvar directive on the Test::data member. In your test.i file:

%naturalvar Test::data;
%include "test.hh"

As described in the SWIG documentation on C and C++ members, SWIG will default to accessing nested structs and classes via pointers. The %naturalvar directs the interface to be accessed by value rather than by reference.

ets
  • 71
  • 1
  • 4
  • However, now I can't change the elements of data. If I do `t = test.Test(); t.data = [1, 2, 3]; t.data[0] = 4`, it fails on the last line and says "'tuple' object does not support item assignment". – Daniel Matz Oct 07 '15 at 19:14
0

Have a look at the typemaps example chapter from the SWIG documentation: http://www.swig.org/Doc2.0/SWIGDocumentation.html#Typemaps_nn40 (at the end of the example where it discusses struct access).

You probably need to add a memberin typemap for your data member, and maybe out and in as well, if those are not already provided by SWIGs std_vector.i.

schlenk
  • 7,002
  • 1
  • 25
  • 29
  • The `memberin` typemap applies to an already converted input. The error seems to be occurring before that. The wrapper for times2 calls swig::asptr, which works, while the wrapper for setting the data variable calls SWIG_ConvertPtr, which fails. So maybe you are on the right track, but I need to find the proper typemap to fix... – Daniel Matz Mar 19 '14 at 18:39