2016-08-08 40 views
1

Im Moment habe ich eine Funktion, die eine Struktur als Puffer verwendet, um einige Informationen zurückgeben, etwa so:SWIG: Wie man eine Struktur mit% apply zurückgibt? ‚Keine typemaps definiert‘ Warnung

int example_reader(int code, void* return_struct); 

Mein Ziel ist es zu machen, so dass, wenn ich diese Funktion wickeln SWIG mit Damit es in Python verwendet werden kann, gebe ich die Struktur zusammen mit dem regulären Rückgabewert der Funktion zurück. Bis jetzt habe ich so mit dem Befehl getan, um das% gilt wie folgt:

%apply struct ret_struct *OUTPUT {void* return_struct}; 

Allerdings, wenn ich die obige Zeile in meine .i-Datei hinzufügen und versuche SWIG zu laufen, erhalte ich die folgende Warnung:

„Warnung 453: Kann gelten nicht (struct ret_struct * OUTPUT keine typemaps definiert sind.“

ich glaube, ich bin die .h-Datei enthält, die die Struktur zurückkehren ich versuche definiert, also habe ich hatte Probleme, das Problem ausfindig zu machen Bitte korrigieren Sie mich, wenn das Problem mit der unkorrekten Einbeziehung der Struktur zu tun zu sein scheint Ich habe versucht, die SWIG-Dokumentation sowie andere Stack Overflow po durchzulesen M, um eine Ahnung davon zu bekommen, was das Problem sein könnte, aber ich konnte es bis jetzt nicht herausfinden. Das Problem wird etwas komplizierter gemacht, weil ich versuche, einen void-Zeiger auf eine Struktur zurückzugeben, und der Code, den ich zu umbrechen versuche, könnte mehrere Arten von Strukturen haben, die ich zurückgeben kann. Was wäre ein kluger Weg, die Rückkehr dieser Struktur zu bewältigen? Vielen Dank!

+1

Ihre Zielsprache brauchen eine Definition für 'struct ret_struct', so kann man nicht zurückgeben 'void *'. Wenn Sie eine Struktur zuweisen möchten, benötigen Sie einen Doppelzeiger oder eine Zeigerreferenz. Ein typisches Szenario besteht darin, eine Schnittstelle 'typedef struct ReturnStructIF' zu definieren und eine Funktion zu erzeugen, die eine Instanz einer solchen Schnittstelle generiert, und 'int CreateSpecializedStructure (ReturnStructIF ** obj)' und eine Funktion für diese Schnittstelle definiert. –

+0

Können Sie vielleicht ein Beispiel geben? Vielen Dank! – GenericAlias

+1

Fertig. Sie könnten in Erwägung ziehen, die letzten drei Zeilen beginnend mit 'SWIG_NewPointerObj' in die if-Klausel zu verschieben, um nur einen Fehlercode zurückzugeben, wenn Ihr Konstruktor nicht 0 zurückgibt (für Erfolg). –

Antwort

2

Ich habe hier ein vollständiges C-Beispiel angegeben, bei dem eine Schnittstelle verwendet wird, um eine Struktur zusammen mit einem Rückgabewert in die Zielsprache zurückzugeben. Auf diese Weise können Sie eine geeignete Schnittstelle erstellen, in der keine Implementierung in der Kopfzeile angegeben ist. Das ist keine Standardimplementierung eines virtuellen Destruktors. Wenn Sie keine Schnittstelle verwenden möchten, können Sie SWIG und Python wissen lassen, wie Daten dargestellt werden.

Interface Kopfleiste: foo.h

typedef struct _Foo Foo; 

int foo_new(Foo **obj); 
int foo_free(Foo *obj); 

int foo_get_value_a(Foo *obj, int *result); 
int foo_set_value_a(Foo *obj, int value); 

int foo_get_value_b(Foo *obj, char **result); 
int foo_set_value_b(Foo *obj, char *value); 

SWIG Schnittstelle: foo.i

%module foo 
%{ 
#include "foo.h" 
%} 

%include "typemaps.i" 

%typemap(in, numinputs=0) Foo ** (Foo *temp) { 
    $1 = &temp; 
} 

%typemap(argout) Foo ** { 
    PyObject* temp = NULL; 
    if (!PyList_Check($result)) { 
    temp = $result; 
    $result = PyList_New(1); 
    PyList_SetItem($result, 0, temp); 
    } 
    temp = SWIG_NewPointerObj(*$1, SWIGTYPE_p__Foo, SWIG_POINTER_NEW); 
    PyList_Append($result, temp); 
    Py_DECREF(temp); 
} 

%delobject foo_free; // Protect for double deletion 

struct _Foo {}; 
%extend _Foo { 
    ~_Foo() { 
    foo_free($self); 
    } 
}; 
%ignore _Foo; 

Einige Implementierung der Schnittstelle: foo.c

%include "foo.h" 

#include "foo.h" 
#include "stdlib.h" 
#include "string.h" 

struct FooImpl { 
    char* c; 
    int i; 
}; 

int foo_new(Foo **obj) 
{ 
    struct FooImpl* f = (struct FooImpl*) malloc(sizeof(struct FooImpl)); 
    f->c = NULL; 
    *obj = (Foo*) f; 
    return 0; 
} 
int foo_free(Foo *obj) 
{ 
    struct FooImpl* impl = (struct FooImpl*) obj; 
    if (impl) { 
    if (impl->c) { 
     free(impl->c); 
     impl->c = NULL; 
    } 
    } 
    return 0; 
} 

int foo_get_value_a(Foo *obj, int *result) 
{ 
    struct FooImpl* impl = (struct FooImpl*) obj; 
    *result = impl->i; 
    return 0; 
} 
int foo_set_value_a(Foo *obj, int value) 
{ 
    struct FooImpl* impl = (struct FooImpl*) obj; 
    impl->i = value; 
    return 0; 
} 

int foo_get_value_b(Foo *obj, char **result) 
{ 
    struct FooImpl* impl = (struct FooImpl*) obj; 
    *result = impl->c; 
    return 0; 
} 
int foo_set_value_b(Foo *obj, char *value) 
{ 
    struct FooImpl* impl = (struct FooImpl*) obj; 
    int len = strlen(value); 
    if (impl->c) { 
    free(impl->c); 
    } 
    impl->c = (char*)malloc(len+1); 
    strcpy(impl->c,value); 
    return 0; 
} 

Script für

Bau

Verbrauch:

import foo 

OK, f = foo.foo_new() 
OK = foo.foo_set_value_b(f, 'Hello world!') 
OK = foo.foo_free(f) 

OK, f = foo.foo_new() 
# Test safe to double delete 
del f 
+0

Vielen Dank für die Hilfe, der Beispielcode ist sehr nützlich und erlaubt mir, mein Problem zu beheben. – GenericAlias

+0

Sind Sie der Autor von [diesem Blogeintrag] (http://jim-jotting.blogspot.co.uk/2014/08/swig-python-and-opaque-structs.html)? – jojek