在下面的测试程序中,我观察到一种奇怪的与ctype相关的行为:
import ctypes as ct
def _pyfunc(a_c_string):
print(type(a_c_string))
a_c_string.value = b"87654321"
return -123
my_str_buf = ct.create_string_buffer(b"test1234")
print(type(my_str_buf))
my_str_buf[3] = b'*'
print(my_str_buf.value)
my_str_buf.value = b"4321test"
print(my_str_buf.value)
signature = ct.CFUNCTYPE(ct.c_int, ct.c_char_p)
pyfunc = signature(_pyfunc)
pyfunc(my_str_buf)
print(my_str_buf.value)该示例通过ctypes在python函数中封装可调用的python c++。目标是传递python函数一个指向c字符串的指针,让它修改它的内容(提供假值),然后返回给调用者。
我首先通过ctype函数create_string_buffer创建了一个可变的字符串缓冲区。从示例中可以看出,字符串缓冲区确实是可变的。
之后,我使用ctypes.CFUNCTYPE(ct.c_int, ct.c_char_p)创建一个c函数原型,然后用我的python函数实例化这个原型,这个函数应该使用相同的签名来调用。最后,我使用可变字符串缓冲区调用python函数。
让我恼火的是,当调用函数时,传递给该函数形状的参数从<class 'ctypes.c_char_Array_9'>类型转移到<class 'bytes'>类型。不幸的是,原始的可变数据类型变成了一个完全无用的不可变字节对象。
这是个虫吗?Python版本为3.6.6。
这是输出:
<class 'ctypes.c_char_Array_9'>
b'tes*1234'
b'4321test'
<class 'bytes'>
Traceback (most recent call last):
File "_ctypes/callbacks.c", line 234, in 'calling callback function'
File "C:/Users/andree/source/Python_Tests/ctypes_cchar_prototype.py", line 5, in _pyfunc
a_c_string.value = b"87654321"
AttributeError: 'bytes' object has no attribute 'value'
b'4321test'预期产出:
<class 'ctypes.c_char_Array_9'>
b'tes*1234'
b'4321test'
<class 'ctypes.c_char_Array_9'>
b'87654321'发布于 2020-12-17 16:51:21
ctypes.c_char_p自动转换为Python bytes。如果您不想要这种行为,请使用以下任何一种:
ctypes.POINTER(ctypes.c_char))class PCHAR(ctypes.c_char_p): pass (导子抑制行为)请注意,LP_c_char没有.value属性,因此我必须直接取消引用指针以影响值的更改。
此外,请注意不要超过传入的可变缓冲区的长度。我添加了length作为附加参数。
示例:
import ctypes as ct
@ct.CFUNCTYPE(ct.c_int, ct.POINTER(ct.c_char), ct.c_size_t)
def pyfunc(a_c_string,length):
new_data = b'87654321\x00' # ensure new null termination is present.
if len(new_data) > length: # ensure new data doesn't exceed buffer length
return 0 # fail
for i,c in enumerate(new_data):
a_c_string[i] = c
return 1 # pass
my_str_buf = ct.create_string_buffer(10)
result = pyfunc(my_str_buf,len(my_str_buf))
print(result,my_str_buf.value)
my_str_buf = ct.create_string_buffer(8)
result = pyfunc(my_str_buf,len(my_str_buf))
print(result,my_str_buf.value)1 b'87654321'
0 b''https://stackoverflow.com/questions/65340776
复制相似问题