Menu

#1210 %shared_ptr(std::vector) broken

open
nobody
python (260)
5
2024-01-25
2011-12-05
Anonymous
No

This concerns python bindings produced by SWIG 2.0.4. When std::vector<T> is instantiated after having been marked as %shared_ptr, the implementation of some methods (e.g. __setitem__) is incorrect. Here's a small test module that shows the problem:
------------------
%module fail

%include "boost_shared_ptr.i"
%include "std_vector.i"

%{
#include <vector>
#include "boost/shared_ptr.hpp"
%}

%shared_ptr(std::vector<int>);
%template(IntVec) std::vector<int>;
------------------

When exercising the generated code, I get:

------------------
>>> import fail
>>> v = fail.IntVec()
>>> v.append(0)
>>> v.append(1)
>>> v.append(2)
>>> v[0] = v[1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "fail.py", line 117, in __setitem__
def __setitem__(self, *args): return _fail.IntVec___setitem__(self, *args)
NotImplementedError: Wrong number or type of arguments for overloaded function 'IntVec___setitem__'.
Possible C/C++ prototypes are:
std::vector< int >::__setitem__(PySliceObject *,std::vector< int,std::allocator< int > > const &)
std::vector< int >::__setitem__(PySliceObject *)
std::vector< int >::__setitem__(std::vector< int >::difference_type,std::vector< int >::value_type const &)
------------------

I don't understand the SWIG standard library well enough to fix this, but my guess is that the problem comes from std/std_vector.i containing the line:

%typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector<Type_, Alloc_ >);

prior to the declaration of std::vector methods. Presumably that overwrites some of the typemaps set up by %shared_ptr and causes wonky argument type-checking code to get generated. In case it helps understand the problem, my current work-around is below. The strategy is to introduce a partial specialization of std::vector, with the %typemap_traits_ptr invocation moved to the end of the class.

------------------
%module example

%include "boost_shared_ptr.i"
%include "std_vector.i"

%define %shared_vec(NAME, TYPE...)
namespace std {
template <class _Alloc >
class vector<TYPE, _Alloc > {
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef TYPE value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef TYPE& reference;
typedef const TYPE& const_reference;
typedef _Alloc allocator_type;

%traits_swigtype(TYPE);

%fragment(SWIG_Traits_frag(std::vector<TYPE, _Alloc >), "header",
fragment=SWIG_Traits_frag(TYPE),
fragment="StdVectorTraits") {
namespace swig {
template <> struct traits<std::vector<TYPE, _Alloc > > {
typedef pointer_category category;
static const char* type_name() {
return "std::vector<" #TYPE " >";
}
};
}
}

%swig_vector_methods(std::vector<TYPE, _Alloc >);
%std_vector_methods(vector);

%typemap_traits_ptr(SWIG_TYPECHECK_VECTOR, std::vector<TYPE, _Alloc >);
};
}

%shared_ptr(std::vector<TYPE >);
%template(NAME) std::vector<TYPE >;

%enddef

%shared_vec(IntVec, int);
------------------

Discussion

  • Olly Betts

    Olly Betts - 2022-03-18

    Same error from example above with current git master and Python3.

     
  • Olly Betts

    Olly Betts - 2024-01-25

    Still happens with current git master (shortly after SWIG 4.2.0) except the error is now a TypeError:

    TypeError: Wrong number or type of arguments for overloaded function 'IntVec___setitem__'.
    
     

Log in to post a comment.