GDAL: prendi il puntatore / maniglia dell'oggetto di sottostante c
Domanda
Ho la seguente configurazione:
- .
- Libreria GDAL con Binding Python (Swig)
- alcuni codici colla (Python)
- una libreria C, interfacciata con ctypes
Voglio passare il puntatore del set di dati sottostanti / maniglia dell'oggetto Dataset
Swig alla mia libreria C.Come posso recuperare questo puntatore?
I Do NON Vuoi interfacciare la libreria C con Swig.
Soluzione
È stato in realtà abbastanza facile, e spero che la mia soluzione sia portatile.Dato, che la mia definizione della funzione C sembra un po 'come questa:
int myfunc(GDALDatasetH ds);
.
Allora la mia definizione ctypes
è come questa:
_lib = C.LibraryLoader(C.CDLL).LoadLibrary(lib_path)
_myfunc = _lib.myfunc
_myfunc.argtypes = [C.c_void_p]
_myfunc.restype = C.POINTER(C.c_char)
.
E posso chiamare la funzione C con:
ds = gdal.Open(path)
...
_myfunc(C.c_void_p(long(ds.this)))
. Altri suggerimenti
La mia prenotazione con l'approccio ctypes per questo problema è che il conteggio di riferimento dell'oggetto DS non viene incrementato automaticamente e diventerà un brutto puntatore se dovesse uscire dalla portata.
Un approccio migliore sarebbe quello di definire un modulo di estensione P Python che gestirebbe il contatore di riferimento dei dati.
Sto usando un Pyobject statico * per tenere l'oggetto, ovviamente una vera implementazione lo memorizzerebbe più intelligente.
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);
}
.