在C
中,我有一个函数,期望包含unsigned char
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
如何从字符串中获取“真实”指针?
编辑:David Cullen提供了一种将字符串指针作为参数的解决方案:
writedata.argtypes = [c_char_p, c_int]
很好,但是我想同时向该函数提供 byte数组和 string 。这意味着这也应该起作用
ll = [0,1,2,3,4,5,6,7]
uints = (c_ubyte*8)(*ll)
writedata(uints, 8)
我很好奇为什么不能两者都做,因为就内存而言,我认为字节数组和字符串应该相同?也许这全部与指针转换有关?
我还尝试了两个ctypes
与同一个C
函数的连接,但这不起作用。
解决方案:我已经重新制定了问题,并在此处获得了最佳答案:
答案 0 :(得分:1)
如果我们转换字符串以匹配所需的参数类型,我们可以使用相同的函数
def writedata(value):
if isinstance(value, str):
value = (ctypes.c_ubyte * len(value)) (*bytearray(value))
writedataf(value, len(value))
为了检验我的理论,我创建了一个非常简单的库:
#include <stdio.h>
void writedata(unsigned char *datapos, int datanum) {
for (int index = 0; index < datanum; index++) {
putchar(datapos[index]);
}
putchar('\n');
}
我使用创建了一个macOS共享库
clang -Wall -Werror -shared -fpic main.c -o libwritedata.so
我将共享库设置为/usr/local/lib
,并创建了以下Python脚本:
import ctypes
writedataf = ctypes.CDLL('/usr/local/lib/libwritedata.so').writedata
writedataf.argtypes = [ctypes.POINTER(ctypes.c_ubyte), ctypes.c_int]
def writedata(value):
if isinstance(value, str):
value = (ctypes.c_ubyte * len(value)) (*bytearray(value))
writedataf(value, len(value))
x = "a short string"
writedata(x)
uints = (ctypes.c_ubyte * len(x)) (*bytearray(x))
writedata(uints)
输出
a short string
a short string