Search code examples
c++python-2.7pointersswigderived-class

in python, I use derived class of Base which is a Base class wrappered by SWIG, but failed with error info: argument 2 of type 'Base *'


// a.h
class A 
{
public:
void register(Base*);
}

// a.cpp
void A::register(Base* pBase)
{
    pBase->run();
}

// Base.h
class Base
{
public:
virtual void run()=0;
}

Then, I use SWIG 3.0 to wrapper this Class A's function register with module.i

// module.i
%module(directors=1) myModule

%{
#include "a.h"
#include "Base.h"
#include <boost/shared_ptr.hpp>
%}

%include  <boost_shared_ptr.i>
%shared_ptr(Base)

%include "a.h"
%feature("director") BaseCase;  // force no abstract for BaseCase
%include "Base.h"

Then, I use derived class of Base in python, but failed with error info: argument 2 of type 'Base *'

# deriveClass.py
class deriveClass(myModule.Base):
    def __init__(self):
        myModule.Base.__init__(self)
    def run(self):
        print('derived class')

Test script as below:

test.py

import myModule
import deriveClass
a=myModule.A()
a.register(deriveClass.deriveClass()) # error found here.

Solution

  • Well, After reference to Wiki(http://www.swig.org/Doc1.3/Typemaps.html) I fixed it. I give a example as below:

    // a.cpp
    #include "a.h"
    
    void A::re(Base* pBase)
    {
        // pBase->run();
        baseList.push_back(pBase);
    }
    
    void A::notifyrun()
    {
        vector<Base*>::iterator iter = baseList.begin();
        for (; iter != baseList.end();iter++)
        {
            (*iter)->run();
        } 
    }
    
    // a.h
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class Base
    {
    public:
    virtual void run()=0;
    };
    
    
    class A 
    {
    public:
        void re(Base* pBase);
        void notifyrun();
    private:
        vector<Base*> baseList;
    };
    
    // module.i
    %module(directors=1) myModule
    
    %{
    #include "a.h"
    #include <iostream>
    #include <boost/shared_ptr.hpp>
    %}
    
    %include "std_string.i"
    %include "std_map.i"
    
    %include  <boost_shared_ptr.i>
    %shared_ptr(Base)
    
    %feature("director") Base;  // force no abstract for BaseCase
    %include "a.h"
    
    // test script 
    import sys
    sys.path.append(".")
    import myModule
    
    
    class deriveClass(myModule.Base):
        def __init__(self):
            myModule.Base.__init__(self)
        def run(self):
            print('derived class')
    
    deriveClass = deriveClass()
    deriveClass.run()
    
    a = myModule.A()
    a.re(deriveClass)
    a.notifyrun()
    

    firstly, compile a.o with command:

    g++ -fPIC -o a.o -c a.cpp
    

    secondly, use swig to generate wrapper file.

    swig -c++ -python module.i
    

    finally, build a _myModule.so

    g++ -fPIC -Wall -Wextra -shared a.o -o _myModule.so module_wrap.cxx -I/usr/include/python2.7 -lpython2.7
    

    Now, you can run the script in python

    python deriveClass.py
    derived class
    derived class