2012-03-13 2 views
1

У меня есть следующие настройки:GDAL: Получить указатель/дескриптор нижележащего объекта C

  • GDAL библиотека с привязками Python (Swig)
  • Некоторого клеем код (Python)
  • библиотека AC, сопрягаемым с ctypes

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

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

ответ

1

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

Мое резервирование с помощью подхода 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); 
} 
+0

Я согласен, это имеет некоторую юридическую силу, но имеет дополнительную проблему, требующую этапа компиляции во время установки, и запрещает отправку чистого пакета python. (Это не для меня). В моем решении указатель никогда не хранится дольше, чем для вызова функции C. Поэтому проблема наличия устаревшего указателя никогда не возникает. – Constantinius