2013-04-03 31 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