Python 将字符串作为c_字节数组传递给c
在Python 将字符串作为c_字节数组传递给c,python,c,ctypes,Python,C,Ctypes,在C中,我有一个函数需要无符号字符数组s void writedata(unsigned char *datapos, int datanum) 我想从Python中传递一个标准字符串 writedata = parallel.writedata writedata.argtypes = [POINTER(c_ubyte), c_int] a = "test string" writedata(a, 11) 据我所知,字符串实际上是一个字节/字符数组,a是一个指针。但是
C
中,我有一个函数需要无符号字符数组
s
void writedata(unsigned char *datapos, int datanum)
我想从Python中传递一个标准字符串
writedata = parallel.writedata
writedata.argtypes = [POINTER(c_ubyte), c_int]
a = "test string"
writedata(a, 11)
据我所知,字符串实际上是一个字节/字符数组,
a
是一个指针。但是,ctypes
不同意:
ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: expected LP_c_ubyte instance instead of str
这很好,但我想为函数提供字节数组s和字符串s。这意味着这也应该起作用
ll = [0,1,2,3,4,5,6,7]
uints = (c_ubyte*8)(*ll)
writedata(uints, 8)
我很好奇为什么我不能同时做这两件事,因为就内存而言,我认为字节数组和字符串应该是相同的?也许这都是关于指针转换的
我还尝试将两个ctypes
连接到同一个C
函数,但这不起作用
解决方案:我重新制定了问题,并在这里得到了最佳答案:
如果我们转换字符串以匹配所需的参数类型,则可以使用相同的函数:
def writedata(值):
如果isinstance(值,str):
value=(ctypes.c_ubyte*len(value))(*bytearray(value))
writedaf(值,len(值))
为了验证我的理论,我创建了一个非常简单的库:
#包括
void writedata(无符号字符*datapos,int-datanum){
for(int index=0;index
我使用
clang-Wall-Werror-shared-fpic main.c-o libwritedata.so
我将共享库修改为/usr/local/lib
,并创建了以下Python脚本:
导入ctypes
writedata=ctypes.CDLL('/usr/local/lib/libwritedata.so')。writedata
writedataf.argtypes=[ctypes.POINTER(ctypes.c_ubyte),ctypes.c_int]
def writedata(值):
如果isinstance(值,str):
value=(ctypes.c_ubyte*len(value))(*bytearray(value))
writedaf(值,len(值))
x=“短字符串”
写入数据(x)
uints=(ctypes.c_ubyte*len(x))(*bytearray(x))
写入数据(uints)
输出
短字符串
短线
我想你会发现这个问题很有用:@IkarusDeveloper它必须是ctypes
。我已经编写了一个巨大的程序,所有其他的Python
C
通信都是通过ctypes
完成的。“据我所知,字符串实际上是一个字节/字符数组”——C字符串是,但不是Python字符串。Python字符串是Unicode代码点的抽象序列,可能有多个不同的内存表示形式。@user2357112supportsMonica公平参数。如果我知道只有ASCII字符,或者如果我把b
放在前面,即b“test string”
?@Pygmalion:ab
放在前面会使它变成bytes
,而不是str
,所以它应该能工作。+1嗯,哦,它能工作,但我有时用实际的字符/字节数组访问同一个函数,也就是说,uints=(c_ubyte*8)(*列表名称)
,writedata(uints,8)
。我可以同时使用这两种数据类型吗?@Pygmalion我修改了脚本以处理这两种数据类型。我非常感谢您的努力,但这对我来说不起作用,因为我在C库中使用了不同的结构,它必须适用于所有函数。。。如果我加载同一个C库的多个实例,这个struct
s将不可见。@Pygmalion我修改了脚本,使库只加载一次。
ll = [0,1,2,3,4,5,6,7]
uints = (c_ubyte*8)(*ll)
writedata(uints, 8)