从C++;在本机站点上失败 我在C++中有一个共享库(DLL),其中有一些用python使用的C风格的API。有一个函数将C回调作为参数。据我所知,需要Python扩展模块(一个单独的DLL)来实现这一点。此模块应将本机“代理”回调传递给API,然后从该回调调用Python对象。我尝试按如下方式使用它(失败):

从C++;在本机站点上失败 我在C++中有一个共享库(DLL),其中有一些用python使用的C风格的API。有一个函数将C回调作为参数。据我所知,需要Python扩展模块(一个单独的DLL)来实现这一点。此模块应将本机“代理”回调传递给API,然后从该回调调用Python对象。我尝试按如下方式使用它(失败):,python,c++,callback,shared-libraries,ctypes,Python,C++,Callback,Shared Libraries,Ctypes,我正在使用Windows8x64环境和Python2.7.6(32位)以及mingw32位编译器(mingw32)。Python扩展是由distutils构建的。API库可以根据需要进行更改,但是,特定于Python的代码必须保存在单独的库中 这是我的代码,简化了。所有的错误检查都被删除了,但是在执行时,无论是Python API还是Windows API都没有显示任何错误 API库: /* typedef void (*callback_t)(); */ static callback_t s

我正在使用Windows8x64环境和Python2.7.6(32位)以及mingw32位编译器(
mingw32
)。Python扩展是由
distutils
构建的。API库可以根据需要进行更改,但是,特定于Python的代码必须保存在单独的库中

这是我的代码,简化了。所有的错误检查都被删除了,但是在执行时,无论是Python API还是Windows API都没有显示任何错误

API库:

/* typedef void (*callback_t)(); */
static callback_t s_callback = nullptr;

void DLL_PUBLIC set_callback(callback_t callback) {
    s_callback = callback;
}

void DLL_PUBLIC trigger_callback() {
    s_callback(); // <--------------------------(1)
}
C函数
common_callback()
的实现如下:

extern "C" void DLL_PUBLIC common_callback() {
    // <--------------------------------------- (2)
    PyObject *arguments = Py_BuildValue("()");
    PyObject *callback_result = PyEval_CallObject(s_callback, arguments);
    Py_DECREF(arguments);
    Py_XDECREF(callback_result);
}
extern“C”void DLL\u PUBLIC common\u callback(){

//通过为GIL注册线程解决了该问题,如前所述

请注意,原始的API DLL、Python扩展DLL和脚本都是在单线程模式下执行的,并且没有创建额外的线程(无论是否由Python管理)。但是,确实存在同步问题,因为使用也可以工作。(不鼓励使用is;我发现它分析了
信号
模块源,从而得出了上述解决方案。)

我的这种说法是不正确的:

使用调试打印,我将错误追溯到(1)。在(2)点的任何代码都不会执行

一些Python API函数仍然可以工作(例如
Py_BuildValue
Py_Initialize
),但大多数都不能工作(例如
PySys\u WriteStdout
PyObject\u Call
,等等),这一事实误导了我

PyObject* handle_object = PyObject_GetAttrString(library, "_handle");
const HMODULE handle = static_cast<const HMODULE>(
    PyLong_AsVoidPtr(handle_object));
const native_set_callback_t native_api_routine =
    reinterpret_cast<const native_set_callback_t>(
        GetProcAddress(handle, "set_callback"));
native_api_routine(common_callback);
extern "C" void DLL_PUBLIC common_callback() {
    // <--------------------------------------- (2)
    PyObject *arguments = Py_BuildValue("()");
    PyObject *callback_result = PyEval_CallObject(s_callback, arguments);
    Py_DECREF(arguments);
    Py_XDECREF(callback_result);
}
Invoking callback from DLL... Traceback (most recent call last):
  File "script.py", line 14, in <module>
    library.trigger_callback()
WindowsError: exception: access violation reading 0x00000028