Question

I have the following setup:

  • GDAL library with Python bindings (SWIG)
  • Some glue code (Python)
  • A C library, interfaced with ctypes

I want to pass the underlying dataset pointer/handle of the SWIG Dataset object to my C library. How can I retrieve this pointer?

I do not want to interface the C library with SWIG.

Was it helpful?

Solution

It was actually quite easy, and I hope that my solution is portable. Given, that my C function definition looks somewhat like this:

int myfunc(GDALDatasetH ds);

Then my ctypes definition is like this:

_lib = C.LibraryLoader(C.CDLL).LoadLibrary(lib_path)
_myfunc = _lib.myfunc
_myfunc.argtypes = [C.c_void_p]
_myfunc.restype = C.POINTER(C.c_char)

And I can call the C function with:

ds = gdal.Open(path)
...
_myfunc(C.c_void_p(long(ds.this)))

OTHER TIPS

My reservation with the ctypes approach for this problem is that the reference count of the ds object is not incremented automatically and will become a bad pointer if it were to go out of scope.

A better approach would be to define a C python extension module that would manage the data reference counter.

I'm using a static PyObject * to hold the object, obviously a real implementation would store it more intelligently.

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); 
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top