当前位置: 首页 > 面试题库 >

从C ++(或C)回调中调用python方法

范翰池
2023-03-14
问题内容

我正在尝试从C 调用python类中的方法。调用它的C 方法是C ++回调。

在此方法中,当我尝试调用python方法时,它给出了segmentation fault

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

// (pFunc is global variable of type PyObject*)
pFunc = PyDict_GetItemString(pDict, "PlxMsgWrapper");

PlxMsgWrapperpython方法在哪里,将在回调中使用。

在回调中,参数创建为

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);

问题答案:

如果要从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时,可能会导致崩溃和奇怪的行为。

有关更多信息,请参见非Python创建的线程。



 类似资料:
  • 问题内容: 构建与C或C ++库的Python绑定的最快方法是什么? (如果这很重要,我正在使用Windows。) 问题答案: Boost Python库是用于连接Python和C 的框架。它使您可以快速而无缝地将C 类的函数和对象暴露给Python,反之亦然,而无需使用特殊工具-仅使用C 编译器即可。它被设计为以非介入方式包装C 接口,因此您不必为了包装而完全更改C ++代码,从而使Boost.

  • 问题内容: 我想从C中调用一个在python模块中定义的自定义函数。我有一些初步的代码可以做到这一点,但是它只是将输出打印到stdout。 mytest.py 测试文件 如何将返回值提取到C double中并在C中使用它? 问题答案: 如前所述,使用PyRun_SimpleString似乎是个坏主意。 您绝对应该使用C- API(http://docs.python.org/c-api/)提供的方

  • 问题内容: 我正在开发Python / ObjC应用程序,需要从ObjC的Python类中调用一些方法。我已经尝试了几种方法,但都没有成功。 如何从Objective-C调用Python方法? 我的Python类正在Interface Builder中实例化。如何从该实例调用方法? 问题答案: 使用PyObjC。 它包含在Leopard及更高版本中。 它甚至可以与iPython一起使用: ` 要从

  • 本文向大家介绍Python使用ctypes调用C/C++的方法,包括了Python使用ctypes调用C/C++的方法的使用技巧和注意事项,需要的朋友参考一下 python使用ctypes调用C/C++ 1. ctpes介绍 ctypes is a foreign function library for Python. It provides C compatible data types, a

  • 问题内容: 我正在尝试从C ++实现调用Python函数。我以为可以通过函数指针来实现,但是似乎不可能。我一直在使用以完成此任务。 假设在Python中定义了一个函数: 现在,我需要将此函数传递给C ,以便可以从那里调用它。如何在C 端编写代码以实现此目的? 问题答案: 如果可以使用任何名称: 将其传递给需要一个的函数。 如果它在具有相同名称的单个已知名称空间中: 已定义,因此您可以像调用任何函数

  • 问题内容: 我试图从C ++获得一个简单的Java方法调用,而Java调用本机方法。这是Java代码: 我试图在从Java到本机的方法调用过程中从本机代码调用方法。 干净的编译应用停止并显示下一条消息后: 显然,这意味着方法名称错误,但对我来说似乎不错。 问题答案: 如果是对象方法,则需要将该对象传递给: 你正在做什么相当于。 由于你的方法无效,因此应调用: 如果要返回结果,则需要更改JNI签名(