SWilliams SWilliams - 3 months ago 13
C++ Question

How to apply SWIG OUTPUT typemaps for class types in Python?

I am having some trouble generating a Python wrapper around a C++ library using SWIG (version 3.0.6).

My issue relates to applying the OUTPUT typemap, specifically in the case of pointers/references to class types.

To illustrate, this is what I want for standard types, and it works:

// .h
int add(const long arg1,const long arg2,long& resultLong);

// interface.i
%apply long& OUTPUT { long& resultLong };
int add(const long arg1,const long arg2,long& resultLong);

// projectWrapper.py
def add(arg1, arg2):
return _projectWrapper.add(arg1, arg2)
addTerm = _projectWrapper.add

// usage
>>> result = projectWrapper.add(2, 4)
>>> print result
[0, 6L]


You don't have to pass in "resultLong", but it is appended to the result automatically. Great!

However, this doesn't seem to be working as I expect when the output type is some pointer to a class type:

// .h
int GetClassType(const char* name, exportedClassType*& resultPointer);

class exportedClassType
{...}

// interface.i
%apply exportedClassType*& OUTPUT { exportedClassType*& resultPointer };
int GetClassType(const char* name, exportedClassType*& resultPointer);

// projectWrapper.py
def GetClassType(name, resultPointer):
return _projectWrapper.GetClassType(name, resultPointer)
GetClassType = _projectWrapper.GetClassType


The problem seems to be that SWIG has not processed it in the same way as the simple type. It still appears as an "input" parameter in the wrapped function signature.

// attempted usage
>>> classType = projectWrapper.GetClassType("name")
TypeError: GetClassType() takes exactly 2 arguments (1 given)

>>> result = 0
>>> projectWrapper.GetClassType("name", result)
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: in method 'GetClassType', argument 2 of type 'exportedClassType *&'


Can somebody please tell me what I'm doing wrong or point me in the right direction? Any help gratefully received! Thanks

Answer

It is not an answer, just not enough of reputaiton for a comment :(

Cause you need to use pointer in C++ and Python doesn't have pointers (so you could not do anything with your current 'result' in Python anyway).

Could you add wrappers to hide pointers into .h as was suggested by @Jens Munk:

class exportedClassType_ptr {
public:
    exportedClassType* ptr;
    exportedClassType_ptr( exportedClassType& input ) {
        this->ptr = &input;
    }
};

int GetClassType( const char* name, exportedClassType_ptr& resultPointer ) {
    return GetClassType( name, resultPointer.ptr );
}

modify .i file to call new method:

%apply exportedClassType_ptr& OUTPUT { exportedClassType_ptr& resultPointer };    
int GetClassType( const char* name, exportedClassType_ptr& resultPointer );

in Python write something like this:

>>> realResult = projectWrapper.exportedClassType()
>>> result = projectWrapper.exportedClassType_ptr(realResult)
>>> projectWrapper.GetClassType("name", result)

and use 'realResult' for future work.

Comments