gpt4 book ai didi

python - 在 DLL 中嵌入 Python : Access violation reading location when Py_DECREF list object

转载 作者:行者123 更新时间:2023-12-04 20:51:36 25 4
gpt4 key购买 nike

我正在尝试将 Python 嵌入到 XLL 中,以允许在 Excel 中调用 Python 函数。 XLL 是一个 DLL,它还至少包含 2 个函数,这些函数告诉 Excel 如何从 DLL 注册或取消注册导出的函数,因此可以完全将其视为传统 DLL。我遇到的问题是当减少 Python 列表对象的引用计数时,程序崩溃并出现以下错误:

Exception thrown at 0x1E14E37D (python37.dll) in EXCEL.EXE: 0xC0000005: Access violation reading location 0x00000064.



减少引用计数字符串、浮点数、 bool 值等时我没有这个问题。只有列表和元组对象给我这个问题。

下面我做了一个简单的例子,其中有 2 个函数暴露给 Excel,testFloat 和 testList。两者都非常容易尝试和调试问题,因此这些函数都没有参数,并且都将 xltypenil 返回到 Excel,这将用 0 填充单元格。每个函数创建自己的 Python 对象(浮点数或列表),然后递减引用计数。
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <Windows.h>
#include <XLCALL.H>
#include <FRAMEWRK.H>

LPCWCHAR uFuncs[][3]{
{L"testFloat", L"Q", L"testFloat"},
{L"testList", L"Q", L"testList"},
};

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

int WINAPI xlAutoOpen(void) {
if (!Py_IsInitialized()) {
Py_InitializeEx(0);
}

// register functions with Excel
XLOPER12 xDLL;
Excel12f(xlGetName, &xDLL, 0);
for (int i{ 0 }; i < sizeof(uFuncs) / sizeof(uFuncs[0]); i++) {
Excel12f(xlfRegister, 0, 4,
(LPXLOPER12)& xDLL,
(LPXLOPER12)TempStr12(uFuncs[i][0]),
(LPXLOPER12)TempStr12(uFuncs[i][1]),
(LPXLOPER12)TempStr12(uFuncs[i][2])
);
}
Excel12f(xlFree, &xDLL, 0);

return 1;
}

int WINAPI xlAutoClose(void) {
if (Py_IsInitialized()) {
Py_FinalizeEx();
}
return 1;
}

LPXLOPER12 testFloat(void) {
static XLOPER12 xRet;
PyObject* obj{ PyFloat_FromDouble(2.5) };
Py_DECREF(obj);
xRet.xltype = xltypeNil;
return &xRet;
}

LPXLOPER12 testList(void) {
static XLOPER12 xRet;
PyObject* obj{ Py_BuildValue("[dd]", 3.4, 4.5) };
Py_DECREF(obj); // <---- This is where the debugger says the error is
xRet.xltype = xltypeNil;
return &xRet;
}

目前我收到以下错误:

Exception thrown at 0x1E14E37D (python37.dll) in EXCEL.EXE: 0xC0000005: Access violation reading location 0x00000064.



我希望它可以正常运行,并将 0 返回到调用该函数的 Excel 单元格。

最佳答案

您需要先获取 GIL,然后才能安全地使用 python C API 执行任何操作。直接报价from the python api doc :

PyGILState_STATE gstate;
gstate = PyGILState_Ensure();

/* Perform Python actions here. */
result = CallSomeFunction();
/* evaluate result or handle exception */

/* Release the thread. No Python API allowed beyond this point. */
PyGILState_Release(gstate);
我建议使用 pybind11而不是直接处理python API。
更进一步,我建议使用或至少抄袭 my Excel/Python library 中的代码它允许您直接在 Excel 和 python 之间进行交互,而无需接触 C API!

关于python - 在 DLL 中嵌入 Python : Access violation reading location when Py_DECREF list object,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58249457/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com