【问题标题】:Calling python object's method from c++从 C++ 调用 python 对象的方法
【发布时间】:2016-02-17 20:24:43
【问题描述】:

我正在尝试实现以下目标:将 python 对象传递给 c++ 回调链(这在许多流行的 c++ 库中很常见)。在 c++ 代码中,回调传递的对象具有级联/链中连续回调所必需的信息。

这是我编写的一个小测试代码:我们将一个 python 对象传递给一个 c 例程(案例 1)并调用它的方法。这行得通。但是当我将 python 对象传递给 c++ 对象并尝试在 c++ 对象“内部”调用它时,我得到了 segfault.. :(

这里是:

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++ 很糟糕,所以我可能遗漏了一些明显的东西)..?

另外,一些额外的问题:

a)我熟悉 swig 和 swig “导演”.. 但是,我想使用 swig 对代码进行一般包装,但我对这个问题中描述的那种事情进行了自定义包装(即没有导演) .有什么方法可以实现吗?

b) 任何其他建议来实现我在这里想要实现的目标,非常感谢.. 这是可能的还是纯粹的精神错乱?

【问题讨论】:

  • 不幸的是,通过 SWIG 将回调函数从 Python 传递到 C++ 还没有得到很好的支持。您需要手写大量的 swig 代码,我相信有一些尝试。

标签: python c++ callback swig


【解决方案1】:

在构造函数中使用

po=this->po

解决了“问题”。对不起垃圾邮件!我将把这个东西留在这里作为例子。也许有人觉得它有用。

【讨论】:

    猜你喜欢
    • 2016-06-19
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-13
    • 2013-05-12
    • 2016-10-11
    相关资源
    最近更新 更多