Мое резервирование с помощью подхода ctypes для этой проблемы заключается в том, что счетчик ссылок объекта ds не увеличивается автоматически и становится плохим указателем, если он должен выйти из области видимости.
Лучшим подходом было бы определить модуль расширения Cython C, который будет управлять счетчиком ссылок на данные.
Я использую статический PyObject * для хранения объекта, очевидно, что реальная реализация сохранит его более разумно.
static PyObject * ds;
PyObject* GiveDsToC(PyObject * self, PyObject * args)
{
PyObject * pThis=NULL;
unsigned long addr;
if(!PyArg_ParseTuple(args, "O", &ds))
return NULL;
/* Ensure the interpreter keeps ds around while we have it */
Py_INCREF(ds);
pThis = PyObject_GetAttrString(ds, "this"); // new reference
addr = PyLong_AsLong(pThis); // convert using __int__ method
Py_DECREF(pThis); // Release the object back
CallSomeCFunction(addr);
Py_RETURN_NONE;
}
void FinishedWithDS(void)
{
// Lock the GIL and decrement the reference counter
PyGILState_STATE state = PyGILState_Ensure();
Py_DECREF(ds);
PyGILState_Release(state);
}
Я согласен, это имеет некоторую юридическую силу, но имеет дополнительную проблему, требующую этапа компиляции во время установки, и запрещает отправку чистого пакета python. (Это не для меня). В моем решении указатель никогда не хранится дольше, чем для вызова функции C. Поэтому проблема наличия устаревшего указателя никогда не возникает. – Constantinius