Pergunta

(This is a question I asked yesterday, but I simplified it)

I've created a class, of which I want two objects as output arguments of a function (called Test below). But when I run the swig command swig -c++ -python swigtest.i I'm getting the error "Warning 453: Can't apply (MyClass &OUTPUT). No typemaps are defined." I tried adding typemaps, but that doesn't help. I also tried using pointers, pointers to pointers and references to pointers, that doesn't help either.

I feel like I've overlooked something simple, because this should be quite a common thing to do. Or do I need to write a complex typemap, like I've seen around but don't understand (yet)?

Below is my code:

MyClass.h (simplified to make it understandable, so switching to just int doesn't help):

class MyClass
{
    int x;
public:
    int get() const
    {
        return x;
    }
};

void Test(MyClass &obj1, MyClass &obj2);

swigtest.i:

%module swigtest

%include typemaps.i

%{
#define SWIG_FILE_WITH_INIT
%}

%{
#include "MyClass.h"
%}

%include "MyClass.h"

%apply (MyClass& OUTPUT)  { MyClass &obj1 }
%apply (MyClass& OUTPUT)  { MyClass &obj2 }
Foi útil?

Solução 3

I settled for adding extra Python code in swigtest.i that wraps the test function, so that I can write obj1, obj2 = Test2(). I still think there must be an easier solution,

// swigtest.i:

%module swigtest

%{
#define SWIG_FILE_WITH_INIT
#include "MyClass.h"
%}

%include "MyClass.h"

%insert("python") %{
    def Test2():
        obj1 = swigtest.MyClass()
        obj2 = swigtest.MyClass()
        swigtest.Test(obj1, obj2)
        return obj1, obj2
%}

Outras dicas

As noted in my previous comment, the %apply OUTPUT trick only works for a limited set of POD types.

For future Swiggers, this solution worked for me (in C# bindings):

%typemap(cstype) CustomType* "out CustomType"
%typemap(csin,
   pre="    $csclassname temp$csinput = new $csclassname();",
  post="    $csinput = temp$csinput;"
) CustomType* "$csclassname.getCPtr(temp$csinput)"

This generates a public interface with an "out" param for CustomType passed by pointer. The internal P/Invoke interface (csim) is left as raw pointers. The "csin" typemap creates a temp variable and assigns to the output parameter.

Also worth noting that in C#, if MyCustomType is already a reference type, you may not need this, however it's strange to have an API that modifies the parameter value without declaring it as "out" (this actually works for my type, but I prefer the explicit out param).

Try:

%module swigtest

%{
#define SWIG_FILE_WITH_INIT
#include "MyClass.h"
%}

%include "typemaps.i"
%apply MyClass *OUTPUT { MyClass &obj1, MyClass &obj2 };

%include "MyClass.h"

You could also create a wrapper that returns a std::list:

%include "std_list.i"
%ignore Test;
%rename(Test) TestWrap;
%inline %{
     std::list<MyClass> TestWrap() {
           MyClass obj1, obj2;
           Test(obj1, obj2);
           std::list<MyClass> tempList;
           tempList.push_back(obj1);
           tempList.push_back(obj2);
           return tempList;
     }
%}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top