【问题标题】:Inconsistent c_char_p behavior between returning vs pointer assignment返回与指针分配之间的 c_char_p 行为不一致
【发布时间】:2019-05-28 16:39:22
【问题描述】:

考虑以下 C 函数:

void AssignPointer(char **p) {
    *p = "Test1";
}

char* Return() {
    return "Test2";
}

现在考虑以下 Python 代码:

import ctypes

lib = CDLL('LibraryPathHere')

lib.AssignPointer.restype = None
lib.AssignPointer.argtypes = (ctypes.POINTER(ctypes.c_char_p),)

lib.Return.restype = ctypes.c_char_p
lib.Return.argtypes = None

def to_python_string(c_str : ctypes.c_char_p) -> str:
    return c_str.value.decode('ascii')

现在以下工作:

c_str = ctypes.c_char_p()
lib.AssignPointer(ctypes.byref(c_str))
print(to_python_string(c_str))

但是下面给出AttributeError: 'bytes' object has no attribute 'value'

c_str = lib.Return()
print(to_python_string(c_str))

在第一种情况下,调试器将c_str 显示为c_char_p(ADDRESS_HERE)。在第二种情况下,调试器将c_str 显示为b'Test2'

那么这是 Python/ctypes 中的错误还是我做错了什么?

【问题讨论】:

    标签: python c string interop ctypes


    【解决方案1】:

    ctypes automatically converts c_char_p 将值返回给字节对象。

    基本数据类型在作为外部函数调用结果返回时,或者例如通过检索结构字段成员或数组项返回时,会透明地转换为原生 Python 类型。换句话说,如果外部函数的 restype 为 c_char_p,您将始终收到 Python 字节对象,而不是 c_char_p 实例。

    如果您想要实际的指针值,请使用ctypes.POINTER(ctypes.c_char) 作为restype

    【讨论】:

    • 如果按设计运行,您能否详细说明如何解决此问题?
    • @SergeRogatch:答案已扩展。
    • 如果我将restype 更改为ctypes.POINTER(ctypes.c_char_p),我会收到错误:AttributeError: 'LP_c_char_p' object has no attribute 'value'
    • @SergeRogatch:首先,它是ctypes.POINTER(ctypes.c_char),而不是ctypes.POINTER(ctypes.c_char_p)。其次,您将需要更多的调整,而不仅仅是换掉重新输入的类型。 c_char_p 是一种“伪原始”类型,其行为与普通指针不同。您将不得不自己处理指针,或者转换回 c_char_p。
    【解决方案2】:

    最后是这个问题的解决方法:

    为避免c_char_pbytes 的自动转换,请将C 函数的restype 设置为c_void_p

    lib.Return.restype = ctypes.c_void_p
    

    然后将cast 转换为c_char_p,然后传递给期望c_char_p 作为常见情况的函数:

    void_ptr = lib.Return()
    c_str = ctypes.cast(void_ptr, ctypes.c_char_p)
    print(to_python_string(c_str))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-26
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多