i have function uses struct buffer return information, so:
int example_reader(int code, void* return_struct);
my goal make when wrap function using swig can used in python, return struct along function's regular return value. far, have been doing using %apply command so:
%apply struct ret_struct *output {void* return_struct};
however, when add above line .i file , try run swig, following warning:
"warning 453: can't apply (struct ret_struct *output. no typemaps defined"
i believe i'm including .h file defines struct i'm trying return, i've had trouble pinpointing issue. please correct me if issue seems involve improper inclusion of struct. i've tried reading through swig documentation other stack overflow posts inkling of problem might be, haven't been able figure out far. problem made trickier because trying return void pointer struct, , code i'm trying wrap have multiple kinds of structs me return. wise way of handling return of struct? thank you!
i have given here full c example, interface used returning struct target language return value. in way can make proper interface, no implementation given in header. no default implementation of virtual destructor. if don't want use interface, can let swig , python know how data represented.
interface header: 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 interface: 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 double deletion struct _foo {}; %extend _foo { ~_foo() { foo_free($self); } }; %ignore _foo;
some implementation of interface: 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 building
#!/usr/bin/env python distutils.core import setup, extension import os os.environ['cc'] = 'gcc'; setup(name='foo', version='1.0', ext_modules =[extension('_foo', ['foo.i','foo.c'])])
usage:
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 double delete del f
Comments
Post a Comment