views:

50

answers:

2

Hi,

So I'm almost done. Now I have working code which calls python callback function.

Only thing I need now is how to pass argument to the python callback function.

My callback.c is:

#include <stdio.h>

typedef void (*CALLBACK)(void);
CALLBACK my_callback = 0;

void set_callback(CALLBACK c);
void test(void);

void set_callback(CALLBACK c) {
  my_callback = c;
}

void test(void) {
  printf("Testing the callback function\n");
  if (my_callback) (*my_callback)();
  else printf("No callback registered\n");
}

My callback.i is:

// An entirely different mechanism for handling a callback

%module callback
%{
typedef void (*CALLBACK)(void);
extern CALLBACK my_callback;

extern void set_callback(CALLBACK c);
extern void my_set_callback(PyObject *PyFunc);

extern void test(void);
%}

extern CALLBACK my_callback;

extern void set_callback(CALLBACK c);
extern void my_set_callback(PyObject *PyFunc);

extern void test(void);

%{
static PyObject *my_pycallback = NULL;
static void PythonCallBack(void)
{
   PyObject *func, *arglist;
   PyObject *result;

   func = my_pycallback;     /* This is the function .... */
   arglist = Py_BuildValue("()");  /* No arguments needed */
   result =  PyEval_CallObject(func, arglist);
   Py_DECREF(arglist);
   Py_XDECREF(result);
   return /*void*/;
}

void my_set_callback(PyObject *PyFunc)
{
    Py_XDECREF(my_pycallback);          /* Dispose of previous callback */
    Py_XINCREF(PyFunc);         /* Add a reference to new callback */
    my_pycallback = PyFunc;         /* Remember new callback */
    set_callback(PythonCallBack);
}

%}

%typemap(python, in) PyObject *PyFunc {
  if (!PyCallable_Check($input)) {
      PyErr_SetString(PyExc_TypeError, "Need a callable object!");
      return NULL;
  }
  $1 = $input;
}

It works well. What should I do so I can pass argument to my_callback? Any help will be greatly appreciated!

Thank you, Joon

A: 

The arguments to the callback are the second argument to PyEval_CallObject(). Right now you're building an empty tuple, which means "no arguments". So, change that. Where you now do:

arglist = Py_BuildValue("()");  /* No arguments needed */

you instead pass Py_BuildValue whatever arguments you want the Python function to receive. For example, if you want to pass the callback an integer, a string and a Python object you got from somewhere, you would do:

arglist = Py_BuildValue("(isO)", the_int, the_str, the_pyobject);
Thomas Wouters
Thanks. But I'm getting callback_wrap.c: In function ‘PythonCallBack’:callback_wrap.c:2801:35: error: ‘the_str’ undeclared (first use in this function)callback_wrap.c:2801:35: note: each undeclared identifier is reported only once for each function it appears in
joon
Thanks. But I'm getting callback_wrap.c: In function ‘PythonCallBack’: \ncallback_wrap.c:2801:35: error: ‘the_str’ undeclared (first use in this function) \ncallback_wrap.c:2801:35: note: each undeclared identifier is reported only once for each function it appears in \neror when I try to compile the code. Is there anywhere else I need to modify? Sorry my knowledge of C programming is very limited.
joon
I did not include the definitions for the_int, the_str and the_pyobject in my example. They would be the things *you* want to pass. It's an example.
Thomas Wouters
Oh .. I need to make static void PythonCallBack(char* the_str) as well. It worked! Thank you so much!
joon
A: 

where do you define my_pycallback? how do you let SWIG know of its existence? what part of your C code invokes PythonCallback?

Matt