smörkex
smörkex

Reputation: 336

SWIG C++ to Python: generate a subclass of Python list

I am using SWIG (v3) to wrap C++ code to Python 3. In C++, I have a class MyClass which inherits from std::vector. I want to wrap this in Python, such that the resulting Python class MyClass is a subclass of the standard Python list class. Is this possible?

Here is an example:

example.h

#include <vector>
#include <iostream>

using namespace std;

// List class
class MyList : public vector<int> 
{
    public:
        // Init
        MyList() : vector<int>() {
            this->insert(this->begin(),2);
            this->insert(this->begin(),1);
        }

        // Toy insert function
        void toy_insert() 
        {
            this->insert(this->begin(),0);
        }
};

example.cpp

#include "example.h"

example.i

%module example

%{
     #include "example.h"
%}

%include "std_vector.i"

using namespace std;

%template(MyVector) std::vector<int>; // Nothing known about base class 'vector< int >' if we remove std:: here

%typemap(out) MyList* {
  int size = (*$1).size();
  $result = PyList_New(size);

  for (int i=0; i<size; i++) {
    PyList_SetItem($result, i, PyInt_FromLong((*$1)[i]));
  }
};

// List class
class MyList : public std::vector<int> // Nothing known about base class 'vector< int >' if we remove std:: here
{
  public:
    MyList();
    void toy_insert();
};

run_example.py

import example

my_list = example.MyList()
print(my_list)

The print command returns <example.MyList; proxy of [1, 2] >, but this is not what I want. Ideally this should just return [1,2], but then I would still be able to call:

my_list.toy_insert()
print(my_list)

which should return [0,1,2].

Thanks for your help

Upvotes: 0

Views: 140

Answers (1)

Mark Tolonen
Mark Tolonen

Reputation: 178409

As mentioned in my comment, you can override the display of a SWIG type. Here's a rough example:

%module x

%{
#include "example.h"
%}

%include <windows.i>
%include <std_vector.i>

%template(MyVector) std::vector<int>;

%include "example.h"

%extend MyList {

const char*__repr__()
{
    // I was lazy.
    return "fancy representation";
}

}

Output:

>>> import x
>>> t=x.MyList()
>>> t
fancy representation
>>> t[0]
1
>>> t[1]
2
>>> t.toy_insert()
>>> t[0]
0
>>> t[1]
1
>>> t[2]
2

Upvotes: 2

Related Questions