GDAL: получить указатель / дескриптор базового объекта C - PullRequest
1 голос
/ 13 марта 2012

У меня есть следующие настройки:

  • Библиотека GDAL с привязками Python (SWIG)
  • Немного кода клея (Python)
  • Библиотека C, сопряженная с ctypes

Я хочу передать базовый указатель / дескриптор набора данных объекта SWIG Dataset в мою библиотеку C. Как я могу получить этот указатель?

Я не хочу связать библиотеку C с SWIG.

Ответы [ 2 ]

1 голос
/ 23 декабря 2015

Мое резервирование с подходом ctypes для этой проблемы заключается в том, что счетчик ссылок объекта ds не увеличивается автоматически и станет плохим указателем, если он выйдет из области видимости.

Лучший подход будетопределить модуль расширения Python 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); 
}
1 голос
/ 13 марта 2012

На самом деле это было довольно легко, и я надеюсь, что мое решение переносимо.Учитывая, что мое определение функции 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)))
...