Нашел более-менее рабочее решение при помощи Python.h. Не знаю, насколько это грамотно, если кто разбирается, поправьте, пожалуйста.
В первом файле описан класс-обертка над PyObject - функцией или объектом Python.
cregister.cpp
#include <python3.4/Python.h>
#include <stdlib.h>
/***********************************************/
/* 1) code to route events to Python object */
/* note that we could run strings here instead */
/***********************************************/
class Caller{
private:
PyObject* Route_Event(int count)
{
PyObject *args, *pres;
/* call Python handler */
args = Py_BuildValue("(i)", count); /* make arg-list */
pres = PyEval_CallObject(Handler, args); /* apply: run a call */
return pres;
}
public:
PyObject *Handler; /* keep Python object in C */
Caller()
{
Handler = NULL; /* keep Python object in C */
}
/*****************************************************/
/* 2) python extension module to register handlers */
/* python imports this module to set handler objects */
/*****************************************************/
void setHandler(PyObject *arg)
{
/* save Python callable object */
Handler = arg;
//Py_XDECREF(Handler); /* called before? */
//PyArg_Parse(arg, "(O)", &Handler); /* one argument */
//Py_XINCREF(Handler); /* add a reference */
}
void triggerEvent(int arg)
{
/* let Python simulate event caught by C */
Route_Event(arg);
}
};
Второй файл - интерфейс для swig:
cregister.i
%module cregister
%{
#include "cregister.cpp"
%}
%include cregister.cpp
makefile для того чтобы собрать все это:
makefile
PYLIB = /usr/local/bin
PYINC = /usr/include/python3.4
CMODS = _cregister.so
CFLAGS = -O3 -fopenmp
all: $(CMODS) cregister.py
# обертка + действительный класс
$(CMODS): cregister_wrap.o cregister.o
g++ $(CFLAGS) -shared cregister_wrap.o cregister.o -L $(PYLIB) -o $@
# генерирует модуль обертки класса
cregister_wrap.o: cregister_wrap.cxx
g++ $(CFLAGS) cregister_wrap.cxx -c -g -fPIC -I $(PYINC)
cregister_wrap.cxx: cregister.i
swig -c++ -python cregister.i
cregister.py: cregister.i
swig -c++ -python cregister.i
# программный код обертки класса C++
cregister.o:
g++ $(CFLAGS) ../wavenet/cregister.cpp -c -g -fPIC -Wno-deprecated
clean:
rm -f *.pyc *.o *.so *.cxx cregister.py
Ну и наконец иллюстрация на Python3:
creg.py
#! /usr/bin/python3
"""
#########################################################################
in Python, register for and handle event callbacks from the C language;
compile and link the C code, and launch this with 'python3 creg.py'
#########################################################################
"""
####################################
# C calls these Python functions;
# handle an event, return a result
####################################
class Caller(object):
def __init__(self, str):
self.str=str
def __call__(self, count):
print(self.str.format(count))
#######################################
# Python calls a C extension module
# to register handlers, trigger events
#######################################
import sys
sys.path.append('you_bin_path/')
import cregister
cal = Caller("Helllo{0}")
cb = cregister.Caller()
print('\nTest1:')
cb.setHandler(cal) # register callback function
for num in range(1, 10):
res = cb.triggerEvent(num) # simulate events caught by C layer