Skip to content Skip to sidebar Skip to footer

SWIG Wrapped Vector Of Vectors (C++ To Python) - How To Recognise The Inner Vector As A Proxy Object?

I'm facing a similar issue to Wrap std::vector of std::vectors, C++ SWIG Python - but it's not just simple C++ parsing. I have the following in my C++ code namespace ns { typed

Solution 1:

I worked on this with a colleague of mine, and we have managed to come up with some solutions.

First of all, in the SWIG .i file, it's important to define this preprocessor variable:

%{
#   define SWIG_PYTHON_EXTRA_NATIVE_CONTAINERS 
%}

And then, to ensure that the references returned from methods such as front(), back(), operator[], etc are actually mapped to the correct proxy type for the internal vector, the following typemaps help:

// In pop()
%typemap(out) std::vector<std::vector<ns::uint64_t> >::value_type { 
$result = SWIG_NewPointerObj(SWIG_as_voidptr(&$1), $descriptor(std::vector<ns::uint64_t>), 0 |  0 ); 
} 

// In front(), back(), __getitem__()
%typemap(out) std::vector<std::vector<ns::uint64_t> >::value_type & { 
    $result = SWIG_NewPointerObj(SWIG_as_voidptr($1), $descriptor(std::vector<ns::uint64_t>), 0 |  0 ); 
} 

We also discovered that if you want the ns::uint64_t to be treated as a python long variable (equivalent to a C unsigned long long) then a few further typemaps were required to ensure the vector methods using values and references would instead just use 64-bit integer values.

// In __getitem__()
%typemap(out) ns::uint64_t {
    $result = PyLong_FromUnsignedLongLong($1);
}
// Not used (but probably useful to have, just in case)
%typemap(in) ns::uint64_t {
    $1 = PyLong_AsUnsignedLongLong($input);
}
// In pop()
%typemap(out) std::vector<ns::uint64_t>::value_type {
    $result = PyLong_FromUnsignedLongLong($1);
}
// In __getitem__(), front(), back()
%typemap(out) std::vector<ns::uint64_t>::value_type & {
    $result = PyLong_FromUnsignedLongLong(*$1);
}
// In __setitem__(), append(), new Uint64Vector, push_back(), assign(), resize(), insert()
// This allows a python long literal number to be used as a parameter to the above methods. 
// Note the use of a local variable declared at the SWIG wrapper function scope,
// by placing the variable declaration in parentheses () prior to the open brace {
%typemap(in) std::vector<ns::uint64_t>::value_type & (std::vector<ns::uint64_t>::value_type temp) {
    temp = PyLong_AsUnsignedLongLong($input);
    $1 = &temp;
}

I hope this solution helps people in future!


Post a Comment for "SWIG Wrapped Vector Of Vectors (C++ To Python) - How To Recognise The Inner Vector As A Proxy Object?"