我有以下设置:
- 带有 Python 绑定的 GDAL 库 (SWIG)
- 一些胶水代码(Python)
- AC 库,与 ctypes 接口
我想将 SWIGDataset
对象的基础数据集指针/句柄传递给我的 C 库。如何检索此指针?
我不想将 C 库与 SWIG 接口。
这实际上很容易,我希望我的解决方案是可移植的。鉴于,我的 C 函数定义看起来有点像这样:
int myfunc(GDALDatasetH ds);
那么我的ctypes
定义是这样的:
_lib = C.LibraryLoader(C.CDLL).LoadLibrary(lib_path)
_myfunc = _lib.myfunc
_myfunc.argtypes = [C.c_void_p]
_myfunc.restype = C.POINTER(C.c_char)
我可以调用 C 函数:
ds = gdal.Open(path)
...
_myfunc(C.c_void_p(long(ds.this)))
我对这个问题的 ctypes 方法的保留是 ds 对象的引用计数不会自动增加,如果超出范围,它将成为一个坏指针。
更好的方法是定义一个 C python 扩展模块来管理数据引用计数器。
我使用静态 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);
}