2014-09-13 172 views
0

我想爲使用ctypes的C庫做一個python包裝。該庫具有需要指向要傳遞的結構的指針的函數,該指針充當未來調用的句柄。通過ctypes中其他結構的指針傳遞結構

該結構具有指向另一個內部結構的指針,該內部結構還具有指向其他結構的指針。

typedef struct varnam { 

    char *scheme_file; 
    char *suggestions_file; 
    struct varnam_internal *internal; 

} varnam; 

varnam_internal該結構具有指針SQLite數據庫等等

struct varnam_internal 
{ 
    sqlite3 *db; 
    sqlite3 *known_words; 

    struct varray_t *r; 
    struct token *v; 
    ... 
} 

我試圖根據this SO回答忽略varnam_internal結構。像

class Varnam(Structure): 
    __fields__ = [("scheme_file",c_char_p), 
        ("suggestions_file",c_char_p),("internal",c_void_p)] 

但是這樣的東西似乎並沒有工作,因爲我覺得庫需​​要分配varnam_internal,才能正常運行。

我應該在Python中實現所有的依賴結構嗎? ctypes適合包裝這樣的圖書館嗎?我已經閱讀了像Cython這樣的替代品,但是我沒有使用Cython的經驗,所以這是可行的嗎?

回答

1

沒有理由在ctypes中定義varnam_internal結構,因爲您應該無需訪問它。無論您是否定義結構,您調用的庫都將分配它。無論遇到什麼問題,都不是因爲你沒有在ctypes中定義結構。

確保您正確地呼叫varnam_init。它使用指針作爲參數的指針,這意味着你不能直接使用你的類Varnam。你會希望做這樣的事情:

from ctypes import * 

class Varnam(Structure): 
    __fields__ = [("scheme_file",c_char_p), 
        ("suggestions_file",c_char_p), 
        ("internal",c_void_p)] 

varnam_ptr = POINTER(Varnam) 

libvarnam = cdll.LoadLibrary("libvarnam.so") # on Linux 
# libvarnam = cdll.libvarnam     # on Windows 

varnam_init = libvarnam.varnam_init 
varnam_init.argtypes = [c_char_p, POINTER(varnam_ptr), POINTER(c_char_p)] 

def my_varnam_init(scheme_file): 
    handle = varnam_ptr() 
    msg = c_char_p() 
    r = varnam_init(scheme_file. handle.byref(), msg.byref()) 
    if r != 0: 
      raise Exception(msg) 
    return handle 

上面的代碼是經過充分測試,但顯示您應該如何調用varnam_init

+0

謝謝。你是對的,我創建了一個Varnam類的指針,並將其用於該函數,而不是指向指針的指針。現在它完美地工作。 – stc043 2014-09-14 10:32:25