简体   繁体   English

从 Python ctypes 返回 c_char_p:是否必须复制结果,如果是,如何复制?

[英]Returning c_char_p from Python ctypes: does the result have to be copied, and if so, how?

I have a function in a library that returns a null-terminated char *, so setup in Python as:我在库中有一个 function,它返回一个空终止的 char *,所以在 Python 中设置为:

my_lib = ctypes.CDLL("my_lib")
my_lib.my_func.restype = ctypes.c_char_p

and this seems to work fine:这似乎工作正常:

my_bytes = my_lib.my_func()
print(my_bytes)

However, the library manages its own memory, and so may manipulate the memory pointed to by char * later on.但是,该库管理自己的 memory,因此稍后可能会操纵char *指向的 memory。 To make sure my_bytes never actually changes, does it need to be copied to another Python object, or has it already been copied?为了确保my_bytes永远不会真正改变,是否需要将它复制到另一个 Python object,或者它已经被复制了? If it does need to be copied, how to do this?如果确实需要复制,该怎么做?

It's already been copied.它已经被复制了。 A c_char_p return is automatically converted to an immutable Python bytes object. If the return type was POINTER(c_char) then you would have a pointer to the actual memory. Sometimes you need the explicit type if you need to pass that pointer to a function to free the memory later. c_char_p返回自动转换为不可变的 Python bytes object。如果返回类型是POINTER(c_char) ,那么您将有一个指向实际 memory 的指针。如果您需要将该指针传递给 function,有时您需要显式类型稍后释放 memory。

A quick proof:快速证明:

from ctypes import *

dll = CDLL('msvcrt')
dll.strcpy.argtypes = c_char_p,c_char_p
dll.strcpy.restype = c_char_p

# strcpy returns a pointer to the destination buffer 'b'
b = create_string_buffer(30)
b2 = dll.strcpy(b,b'hello, world!')
print(b2)
b[0] = b'm'     # alter the destination
print(b.value)
print(b2)       # no change to b2
print()
dll.strcpy.restype = POINTER(c_char)
b3 = dll.strcpy(b,b'hello there!')
print(b3)
print(b3[:12])
b[0] = b'm'     # alter the destination
print(b.value)
print(b3[:12])  # changed!

Output: Output:

b'hello, world!'
b'mello, world!'
b'hello, world!'       # no change

<ctypes.LP_c_char object at 0x000001B65E9A5840>  # the pointer
b'hello there!'        # copied data from pointer
b'mello there!'        # change destination buffer
b'mello there!'        # cpoied data from pointer again, changed!

c_char_p by default returns bytes object. So it will print with b' bytes. c_char_p默认返回字节 object。因此它将打印b'字节。 If need to print as string, we can do with .decode('utf-8')如果需要打印为字符串,我们可以使用.decode('utf-8')

Example:例子:

print(b2) # prints b'hello, world!' as bytes
print(b2.decode('utf-8')) # prints 'hello, world!' as string

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM