Я пытаюсь встроить Python в XLL, чтобы позволить функциям Python вызываться в Excel. XLL - это библиотека DLL, которая также включает как минимум 2 функции, которые сообщают Excel, как регистрировать или отменять регистрацию экспортируемых функций из библиотеки DLL, так что это можно рассматривать точно как традиционную библиотеку DLL. Проблема, с которой я сталкиваюсь, заключается в том, что при уменьшении счетчика ссылок объекта списка Python происходит сбой программы со следующей ошибкой:
Исключение, выданное в 0x1E14E37D (python37.dll) в EXCEL.EXE: 0xC0000005: Доступнарушение чтения местоположения 0x00000064.
У меня нет этой проблемы при уменьшении строк счетчиков ссылок, чисел с плавающей запятой, bool и т. д. Эта проблема возникает только у объекта списка и кортежа.
Ниже я сделал простой пример с двумя функциями, доступными для Excel, testFloat и testList. Обе сделаны очень простыми, чтобы попытаться отладить проблему, поэтому функции не принимают аргументов и оба возвращают xltypenil в Excel, который заполнит ячейку 0. Каждая функция создает свой собственный объект Python (float или список) и затем уменьшает значениеколичество ссылок.
#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;
}
В настоящее время я получаю следующую ошибку:
Исключение, выданное в 0x1E14E37D (python37.dll) в EXCEL.EXE: 0xC0000005: Место чтения нарушения доступа0x00000064.
Я ожидаю, что это запустится без ошибок и вернет 0 в ячейку Excel, вызывающую функцию.