【问题标题】:How to convert a Python 'bytes' object to ctypes 'POINTER(c_byte)'如何将 Python 'bytes' 对象转换为 ctypes 'POINTER(c_byte)'
【发布时间】:2015-12-28 21:28:16
【问题描述】:

我想用这个签名为 C 函数编写一个 ctypes 包装器:

int utp_process_udp(utp_context *ctx, const byte *buf, size_t len, const struct sockaddr *to, socklen_t tolen);

为了进行一些类型检查,我已将其添加到我的 Python 包装器中:

libutp.utp_process_udp.argtypes = [POINTER(UtpContext), POINTER(c_byte), c_size_t, POINTER(sockaddr_in), c_int]

但是当我将 bytes 对象作为 buf 参数传递时,我得到了这个错误:

Traceback (most recent call last):
  File "ucat.py", line 269, in <module>
    main()
  File "ucat.py", line 251, in main
    network_loop()
  File "ucat.py", line 138, in network_loop
    utp.utp_process_udp(ctx, data, addr)
  File "/home/mostafa/source/pyutp/utp.py", line 159, in utp_process_udp
    POINTER(c_byte)(data), c_size_t(len(data)),
TypeError: expected c_byte instead of bytes

如果我不设置argtypes,我可以成功调用该函数,所以显然bytes 对象可以传递给这个函数。我应该做些什么来让 ctypes 知道我在做什么?也许是某种演员? (我已经尝试过使用ctypes.cast 函数,但没有成功。)

【问题讨论】:

    标签: python python-3.x ctypes


    【解决方案1】:

    我只是使用POINTER(c_char) 而不是POINTER(c_byte),问题就消失了。

    【讨论】:

    • 您可以改用c_char_p。请注意,在这种情况下,可以传递不可变的 bytes 对象,因为参数类型被限定为 const byte 指针。
    • @eryksun 文档明确指出 c_char_p 用于以 NULL 结尾的字符串,这显然不是其中之一。
    • 作为一个重要的结果类型,因为 getfunc 会尝试自动创建一个字符串,寻找一个可能不存在的空终止符。这可能会出现段错误,所以是的,这是结果类型的一个重要区别。作为参数类型,一点都不重要。 C 函数看到的只是一个指向字符串第一个字节的指针。
    • 顺便说一句,CPython bytesstr 类型被实现为以空字符结尾的字符串。 c_char_p.from_param 传递对象的内部指针。这就是为什么您必须小心只为标记为const 的参数传递bytesstr。否则,您最终可能会违反 CPython 的不可变对象可以被实习的期望。
    • 另请注意,POINTER 使用类型缓存,并且 POINTER(c_char) 已定义且特殊情况下使用来自c_char_pfrom_param 转换器方法,即@ 中的POINTER(c_char).from_param = c_char_p.from_param 行987654338@函数。
    猜你喜欢
    • 1970-01-01
    • 2018-12-26
    • 1970-01-01
    • 1970-01-01
    • 2022-07-26
    • 1970-01-01
    • 2015-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多