返回与指针分配之间的 c_char_p 行为不一致

Ser*_*tch 0 c python string interop ctypes

考虑以下 C 函数:

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

char* Return() {
    return "Test2";
}
Run Code Online (Sandbox Code Playgroud)

现在考虑以下 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')
Run Code Online (Sandbox Code Playgroud)

现在进行以下工作:

c_str = ctypes.c_char_p()
lib.AssignPointer(ctypes.byref(c_str))
print(to_python_string(c_str))
Run Code Online (Sandbox Code Playgroud)

然而,以下给出AttributeError: 'bytes' object has no attribute 'value'

c_str = lib.Return()
print(to_python_string(c_str))
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,调试器显示c_strc_char_p(ADDRESS_HERE)。在第二种情况下,调试器显示c_strb'Test2'

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

use*_*ica 5

ctypes自动将 c_char_p返回值转换为字节对象。

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

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