Я пытаюсь достичь следующего: передать объект python в цепочку обратного вызова C++ (что характерно для многих популярных библиотек C++). В коде C++ обратные вызовы передают объекты, которые имеют необходимую информацию для последовательных обратных вызовов в каскаде/цепочке.Вызов метода объекта python из C++
Вот небольшой тестовый код, который я написал: мы передаем объект python в подпрограмму c (случай 1) и вызываем его метод. Это работает нормально. Но когда я передать объект питона в объекнтую ++ и попытаться назвать его «внутри» C++ объект, я получаю .. :(выдаст ошибку сегментации
Вот он идет:
C++ модуль («some.cpp»):
#include <stdint.h>
#include <iostream>
#include <Python.h>
/* objective:
* create c++ objects/routines that accept python objects
* then call methods of the python objects inside c++
*
* python objects (including its variables and methods) could be passed along, for example in c++ callback chains ..
* .. and in the end we could call a python callback
*
* Compile and test as follows:
* python setup.py build_ext
* [copy/link some.so where test.py is]
* python test.py
*
*/
class testclass {
public:
testclass(int* i, PyObject* po) {
std::cerr << "testclass constructor! \n";
i=i; po=po;
}
~testclass() {}
void runpo() {
PyObject* name;
const char* mname="testmethod";
name=PyString_FromString(mname);
std::cerr << "about to run the python method .. \n";
PyObject_CallMethodObjArgs(po, name, NULL);
std::cerr << ".. you did it - i will buy you a beer!\n";
}
public:
int* i;
PyObject* po;
};
/* Docstrings */
static char module_docstring[] = "hand-made python module";
/* Available functions */
static PyObject* regi_wrapper(PyObject * self, PyObject * args);
void regi(int* i, PyObject* po);
/* Module specification */
static PyMethodDef module_methods[] = {
{"regi_wrapper",regi_wrapper, METH_VARARGS, "lets see if we can wrap this sucker"},
{NULL, NULL, 0, NULL}
};
/* Initialize the module */
PyMODINIT_FUNC initsome(void)
{
PyObject *m = Py_InitModule3("some", module_methods, module_docstring);
if (m == NULL)
return;
// import_array(); // numpy not required here ..
}
static PyObject* regi_wrapper(PyObject * self, PyObject * args)
{
int* input_i; // whatever input variable
PyObject* input_po; // python object
PyObject* ret; // return variable
// parse arguments
if (!PyArg_ParseTuple(args, "iO", &input_i, &input_po)) {
return NULL;
}
// https://stackoverflow.com/questions/16606872/calling-python-method-from-c-or-c-callback
// Py_INCREF(input_po); // need this, right? .. makes no difference
/* // seems not to make any difference ..
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
*/
regi(input_i, input_po);
// PyGILState_Release(gstate); // .. makes no difference
// Py_DECREF(input_po); // .. makes no difference
Py_RETURN_TRUE;
}
void regi(int* i, PyObject* po) {
// search variable and methods from PyObject "po" and call its methods?
PyObject* name;
const char* mname="testmethod";
testclass* testobj;
testobj=new testclass(i,po);
/* [insert // in front of this line to test case 1]
// ***** this one works! *********
name=PyString_FromString(mname);
PyObject_CallMethodObjArgs(po, name, NULL);
*/ // [insert // in front of this line to test case 1]
// *** I WOULD LIKE THIS TO WORK *** but it gives segfault.. :(
testobj->runpo(); // [uncomment to test case 2]
}
setup.py:
from distutils.core import setup, Extension
# the c++ extension module
extension_mod = Extension("some", ["some.cpp"])
setup(name = "some", ext_modules=[extension_mod])
test.py:
import some
class sentinel:
def __init__(self):
pass
def testmethod(self):
print "hello from sentinel.testmethod"
pass
se=sentinel()
some.regi_wrapper(1,se)
Этот вопрос представляется актуальным:
Calling python method from C++ (or C) callback
.. однако ответ не помог мне.
Что мне не хватает/непонимания здесь (мой C++ отсасывает большое время, поэтому я мог пропустить что-то очевидное) ..?
Кроме того, некоторые бонусные вопросы:
а) Я знаком с глотком и Swig «директорами» .. однако, я хотел бы использовать глотнули для общей упаковки коды, но мой заказ упаковка для сортировки вещей, описанных в этом вопросе (т.е. без директоров). Есть ли способ достичь этого?
b) Любые другие предложения по достижению того, чего я пытаюсь достичь здесь, высоко ценятся .. это возможно или просто чистое безумие?
К сожалению, передача функции обратного вызова из Python в C++ с помощью SWIG еще не очень хорошо поддерживается. Было бы достаточно количество кодов, которые вам нужно было бы написать вручную, и я считаю, что в нем есть несколько попыток. – AndyG