Search code examples
c++swig

How to wrap a class derived from vector in swig


I want to wrap a class derived from std::vector with some extend functions into csharp with swig. the functions from vector are also needed like push_back to add new item into the class (which named Add in csharp).

I tried with default setting with swig, IntArray is valid in csharp .But, vector's functions are invalid.

if i try to define a vector in the .i file:

namespace std{
%template(ScalarVec) vector<ScalarTest>; 
}

a class named ScalarVec have functions like vector is valid in csharp, but without the extend function.

How to wrap the ScalarArray to csharp with swig?

The following is a simple example.

#include <vector>
#include <numeric>
namespace test
{
    struct ScalarTest {
        int val;
    };
    struct ScalarArray : public std::vector<ScalarTest>
    {
        int sum() const { 
            int res = 0;
            for (const ScalarTest &item : *this) {
                res += item.val;
            }
            return res;
        }
    };
}

Solution

  • SWIG is picky about order of declarations. Below correctly wraps your example code and can call the sum function. I'm not set up for C# so the demo is created for Python:

    test.i

    %module test
    
    %{
    // Code to wrap
    #include <vector>
    #include <numeric>
    
    namespace test
    {
        struct ScalarTest {
            int val;
        };
        struct ScalarArray : public std::vector<ScalarTest>
        {
            int sum() const { 
                int res = 0;
                for (const ScalarTest &item : *this) {
                    res += item.val;
                }
                return res;
            }
        };
    }
    %}
    
    namespace test
    {
        struct ScalarTest {
            int val;
        };
    }
    
    %include <std_vector.i>
    // Must declare ScalarTest above before instantiating template here
    %template(ScalarVec) std::vector<test::ScalarTest>;
    
    // Now declare the interface for SWIG to wrap
    namespace test
    {
        struct ScalarArray : public std::vector<ScalarTest>
        {
            int sum() const;
        };
    }
    

    demo.py

    import test
    x = test.ScalarArray()
    a = test.ScalarTest()
    a.val = 1
    b = test.ScalarTest()
    b.val = 2
    x.push_back(a)
    x.push_back(b)
    print('sum',x.sum())
    print(x[0].val,x[1].val)
    

    Output:

    sum 3
    1 2