2013-04-03 62 views
1

我使用ctypes的接口與遺留C DLL Python代碼。 的DLL預期,我給它一個函數指針作爲回調,這則將會從DLL中調用。使用ctypes的寫回調該傳遞在指針的指針參數被用作輸出參數

該回調的C聲明看起來像

char foo(char **buf) 

語義的DLL預期,我讓點BUF到由回調管理和返回0,如果一切正常的字符串緩衝區。在C,這將是靜態的char []變量mybuf和我將與代碼傳遞靜態BUF的地址返回等

*buf = &mybuf[0] ; 
return (char)0 ; 

需要被空終止照例中C.我能夠在mybuf的字符串傳遞函數指針到DLL和現在一個Python(部件)函數

def pyfoo(self, char_ptr_ptr) 

被調用。

類,其中pyfoo定義也初始化(在INIT)字段

self.response=create_string_buffer("The Response String") 

如何傳遞的地址,在此字符串實際上是存儲在內存中的DLL? 由於ctypes的有時會造成拷貝而不是通過地址返回真正的引用我想是這樣

cpointer = c_int.from_address(char_ptr_ptr[0]) 
cpointer.value = addressof(self.response) 
return c_char(0) 

它不工作。 我試圖取消引用傳遞指針,指針和存儲內存地址有其他的方法(如直接存儲(我認爲是字符串的地址)成char-ptr_ptr [0]),但回調的調用者從來都不是做我期待的事情。

如果有人曾經解決過在python中創建一個以null結尾的字符串的問題,並且通過一個**指針將該字符串的地址傳遞給在C中實現的DLL,我會非常感謝他/她解決了這個問題。謝謝!

(編輯),或者是我的問題要簡單得多?是

c_char(0) 

實際上將單個字節推入堆棧作爲返回值?如果沒有,那麼實現一個應該返回一個字節的回調的正確方法是什麼?

+1

你不介意改變標題與您遇到的問題更相關的東西?因爲它是現在,我覺得標題不是非常有用 –

+1

希望新的標題是更好的...... – Chris

回答

0

我會用下面的函數原型:

CFUNCTYPE(c_byte, POINTER(POINTER(c_char))) 

而且寫pyfoo這樣的:

def pyfoo(self, char_ptr_ptr): 
     char_ptr_ptr[0] = self.response 
     return 0 

例如:

>>> import os 
>>> from ctypes import * 

>>> open('tmp.c', 'w').write(r''' 
... #include <stdio.h> 
... typedef char (*callback_t)(char **buf); 
... int test(callback_t foo) 
... { 
...  char res, *buf; 
...  res = foo(&buf); 
...  printf("res: %d\n", res); 
...  printf("buf: %s\n", buf); 
...  return 0; 
... } 
... ''') 
>>> _ = os.system('gcc -shared -fPIC -o tmp.so tmp.c') 
>>> lib = CDLL('./tmp.so') 

>>> class Test(object): 
... def __init__(self): 
...  self.response = create_string_buffer("The Response String") 
...  self.callback = CFUNCTYPE(c_byte, POINTER(POINTER(c_char)))(self.pyfoo) 
... def pyfoo(self, char_ptr_ptr): 
...  char_ptr_ptr[0] = self.response 
...  return 0 
... 

>>> t = Test() 
>>> _ = lib.test(t.callback) 
res: 0 
buf: The Response String 
+0

在我的追求,瞭解ctypes的三分球,得到了明顯失焦。感謝您幫助重新聚焦! – Chris