【问题标题】:Using ctypes to write callbacks that pass-in pointer to pointer parameters to be used as output-parameter使用 ctypes 编写回调,将指针传递给指针参数以用作输出参数
【发布时间】:2013-03-25 01:50:46
【问题描述】:

我正在使用 ctypes 将 Python 代码与旧版 C DLL 连接起来。 DLL 希望我给它一个函数指针以用作回调,然后将从 DLL 中调用它。

该回调的 C 声明如下所示

char foo(char **buf)

从语义上讲,DLL 期望我让 buf 指向由回调管理的字符串缓冲区,如果一切正常,则返回 0。在 C 中,这将是一个静态 char[] 变量 mybuf,我将使用类似

的代码将该静态 buf 的地址传回
*buf = &mybuf[0] ;
return (char)0 ;

mybuf 中的字符串需要像往常一样在 C 中以 null 终止。我能够将函数指针传递给 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 中创建空终止字符串并通过 **pointer 将字符串的地址传递给用 C 实现的 DLL 的问题,我将非常感谢他/她如何解决了这个问题。谢谢!

(编辑)还是我的问题更简单?是

c_char(0) 

实际上将单个字节作为返回值压入堆栈?如果不是,那么实现返回单个字节的回调的正确方法是什么?

【问题讨论】:

  • 您介意将标题更改为与您遇到的问题更相关的内容吗?就目前而言,我发现标题不是很有用
  • 希望新标题更好...

标签: python callback ctypes


【解决方案1】:

我会使用以下函数原型:

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

【讨论】:

  • 在我寻求理解 ctypes 中的指针的过程中,显而易见的事情失去了焦点。感谢您帮助重新集中注意力!
猜你喜欢
  • 2020-11-04
  • 2012-01-24
  • 1970-01-01
  • 2016-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多