3

I'm trying to write a SWIG wrapper for a C library that uses pointers to functions in its structs. I can't figure out how to handle structs that contain function pointers. A simplified example follows.

test.i:

/* test.i */

%module test
%{

typedef struct {
    int (*my_func)(int);
} test_struct;

int add1(int n) { return n+1; }

test_struct *init_test()
{
    test_struct *t = (test_struct*) malloc(sizeof(test_struct));
    t->my_func = add1;
}
%}

typedef struct {
    int (*my_func)(int);
} test_struct;

extern test_struct *init_test();

sample session:

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> t = test.init_test()
>>> t
<test.test_struct; proxy of <Swig Object of type 'test_struct *' at 0xa1cafd0> >
>>> t.my_func
<Swig Object of type 'int (*)(int)' at 0xb8009810>
>>> t.my_func(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'PySwigObject' object is not callable

Anyone know if it's possible to get t.my_func(1) to return 2?

Thanks!

3 Answers 3

1

I found an answer. If I declare the function pointer as a SWIG "member function", it seems to work as expected:

%module test
%{

typedef struct {
  int (*my_func)(int);
} test_struct;

int add1(int n) { return n+1; }

test_struct *init_test()
{
    test_struct *t = (test_struct*) malloc(sizeof(test_struct));
    t->my_func = add1;
    return t;
}

%}

typedef struct {
    int my_func(int);
} test_struct;

extern test_struct *init_test();

Session:

$ python
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> t = test.init_test()
>>> t.my_func(1)
2

I was hoping for something that wouldn't require writing any custom SWIG-specific code (I'd prefer to just "%include" my headers without modification), but this will do I guess.

Sign up to request clarification or add additional context in comments.

Comments

0

You forget to "return t;" in init_test():

#include <stdlib.h> 
#include <stdio.h> 

typedef struct {
 int (*my_func)(int);
} test_struct;

int add1(int n) { return n+1; }

test_struct *init_test(){
  test_struct *t = (test_struct*) malloc(sizeof(test_struct));
  t->my_func = add1;
  return t;
}

int main(){
  test_struct *s=init_test();

  printf( "%i\n", s->my_func(1) );
}

1 Comment

You're right, thanks. Sorry it was an error in transcribing my question from the test code I was using.
0

There is a current work with already satisfacting result about to have C bindings from C++ code.

So the simplest way seems to

  1. Create C++ code instead of C.
  2. Clone this unmerged branch https://github.com/swig/swig/pull/2086 and to compile from source.
  3. Create python bindings.

Then you could use the -c option in order to provide C bindings as well as python. Then your code will be avaible in C as well as in Python.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.