Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从C++;(C)收回_C++_Python_C_Callback_Python C Api - Fatal编程技术网

C++ 从C++;(C)收回

C++ 从C++;(C)收回,c++,python,c,callback,python-c-api,C++,Python,C,Callback,Python C Api,我试图调用C++中的Python类中的方法。从中调用的C++方法是C++回调。< /P> 在这个方法中,当我试图调用python方法时,它给出了分段错误 我已经将python函数的一个实例保存在一个全局变量中,如 // (pFunc is global variable of type PyObject*) pFunc = PyDict_GetItemString(pDict, "PlxMsgWrapper"); 其中PlxMsgWrapper是一个python方法,将在回调中使用 在回调中,

我试图调用C++中的Python类中的方法。从中调用的C++方法是C++回调。< /P> 在这个方法中,当我试图调用python方法时,它给出了
分段错误

我已经将python函数的一个实例保存在一个全局变量中,如

// (pFunc is global variable of type PyObject*)
pFunc = PyDict_GetItemString(pDict, "PlxMsgWrapper");
其中
PlxMsgWrapper
是一个python方法,将在回调中使用

在回调中,参数被创建为

PyObject* args = PyTuple_Pack(2, PyString_FromString(header.c_str()),
                                 PyString_FromString(payload.c_str()));
在创建

PyObject * pInstance = PyObject_CallObject(pFunc, args);
在这一行中,它给出了分段错误。在此之后,实际的python方法被称为

PyObject* recv_msg_func = PyObject_GetAttrString(module, (char *)"recvCallback");
args = PyTuple_Pack(1, pInstance);
PyObject_CallObject(recv_msg_func, args);

Python应该在运行它的目录中查找模块 但是,如果您认为问题在于python没有找到 您可以将计算机上的任意目录添加到 程序中的模块搜索路径:

// Initialize the Python Interpreter
Py_Initialize();

// The following two lines to the trick:
// add path to your module to python's search paths
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append(\"/path/to/python/module/here\")");

// Build the name object
pName = PyString_FromString("your_module");

// Load the module object
pModule = PyImport_Import(pName);

// pDict is a borrowed reference 
pDict = PyModule_GetDict(pModule);

// pFunc is also a borrowed reference 
pFunc = PyDict_GetItemString(pDict, "PlxMsgWrapper");

pArgs = ... 

if (PyCallable_Check(pFunc)) 
{
   PyObject_CallObject(pFunc, pArgs);
} else {
   PyErr_Print();
}

如果要从C/C++回调调用Python函数,需要做一些事情。首先,在保存python函数对象时,需要使用以下命令增加引用计数:

Py_INCREF(pFunc)
否则,Python不知道您正在保留一个对象引用,它可能会对它进行垃圾收集,从而在您试图从回调中使用它时导致分段错误

然后,您需要关心的下一件事是调用C/C++回调时运行的线程。如果您从另一个非Python创建的线程(即在套接字上接收数据的C/C++线程)被回调,那么您必须在调用任何Python API函数之前获得Python的全局解释器锁(GIL)。否则,程序的行为是未定义的。要获得GIL,您需要:

void callback() {
    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();

    // Get args, etc.

    // Call your Python function object
    PyObject * pInstance = PyObject_CallObject(pFunc, args);

    // Do any other needed Python API operations

    // Release the thread. No Python API allowed beyond this point.
    PyGILState_Release(gstate);
}
此外,在扩展模块的init函数中,应执行以下操作以确保线程正确初始化:

// Make sure the GIL has been created since we need to acquire it in our
// callback to safely call into the python application.
if (! PyEval_ThreadsInitialized()) {
    PyEval_InitThreads();
}
否则,当您试图从非Python线程获取GIL时,可能会发生崩溃和奇怪的行为


有关这方面的更多详细信息,请参阅。

这并不能准确回答您的问题,但您可以大大简化代码,避免引用计数问题


我已经尽了最大的努力来恰当地阐明。如果有任何问题,请回复。是否检查PyObject_GetAttrString是否实际返回可用的内容?可能由于某种原因,查找失败。也许“模块”没有正确初始化?@djf实际上,控件本身直到那时才出现
PyObject\u CallObject(pFunc,args)
。它在调用此方法本身时崩溃。为了摆脱模块问题,我没有在回调中加载它。啊,我明白了。我误解了这个问题。您是否可以展示一个完整的代码示例?如果PyObject_CallObject segfaults,很可能是因为pFunc或args没有正确初始化。@djf
args
回调本身中正确初始化。这不是问题<代码>pFunc
在全球范围内存在。我怀疑并正在
回调
本身中初始化
pFunc
。但问题还是来了。非常感谢。:)这正是问题所在。非常感谢——我没有考虑到我可能会走错方向。
#include "boost/python.hpp"

using namespace boost::python;

int main()
{
  Py_Initialize();

  object pyFunPlxMsgWrapper = import("your_module").attr("PlxMsgWrapper");
  pyFunPlxMsgWrapper(2, "string", "data");
  return 0;
}