将ByteArray从Python传递到C函数

将ByteArray从Python传递到C函数,python,c,ctypes,Python,C,Ctypes,我想将一个ByteArray变量从Python程序传递到用C编写的DLL,以加速某些在Python中太慢的特定处理。我浏览过网络,尝试过使用byref、cast、MemoryView、addressof组合的Ctypes,但没有任何效果。有没有简单的方法可以实现这一点,而不必将我的ByteArray复制到其他将要通过的东西中? 以下是我试图做的: /* My C DLL */ __declspec(dllexport) bool FastProc(char *P, int L) { /*

我想将一个ByteArray变量从Python程序传递到用C编写的DLL,以加速某些在Python中太慢的特定处理。我浏览过网络,尝试过使用byref、cast、MemoryView、addressof组合的Ctypes,但没有任何效果。有没有简单的方法可以实现这一点,而不必将我的ByteArray复制到其他将要通过的东西中? 以下是我试图做的:

/* My C DLL */
__declspec(dllexport) bool FastProc(char *P, int L)
{
    /* Do some complex processing on the char buffer */
    ;
    return true;
}

# My Python program
from ctypes import *
def main(argv):
    MyData = ByteArray([1,2,3,4,5,6])
    dll = CDLL('CHELPER.dll')
    dll.FastProc.argtypes = (c_char_p, c_int)
    dll.FastProc.restype = c_bool

    Result = dll.FastProc(MyData, len(MyData))
    print(Result)
但是在将第一个参数(MyData)传递给C函数时,我得到了一个类型错误

有没有一种解决方案不需要太多的开销就可以浪费C函数的好处


Olivier

我假设
ByteArray
应该是
ByteArray
。我们可以使用创建一个可变字符缓冲区,它是
ctypes
数组的
cUchar
。但是
create\u string\u buffer
将不接受
bytearray
,我们需要传递一个
bytes
对象来初始化它;幸运的是,在
字节
字节数组
之间进行转换既快速又高效

我没有你的DLL,所以为了测试数组的行为是否正确,我将使用函数洗牌它的字符

from ctypes import CDLL, create_string_buffer

libc = CDLL("libc.so.6") 

# Some test data, NUL-terminated so we can safely pass it to a str function.
mydata = bytearray([65, 66, 67, 68, 69, 70, 0])
print(mydata)

# Convert the Python bytearray to a C array of char
p = create_string_buffer(bytes(mydata), len(mydata))

#Shuffle the bytes before the NUL terminator byte, in-place.
libc.strfry(p)

# Convert the modified C array back to a Python bytearray
newdata = bytearray(p.raw)
print(newdata)
典型输出

bytearray(b'ABCDEF\x00')
bytearray(b'BFDACE\x00')

什么是ByteArray?它不应该是
bytearray
(全小写)吗?您正在使用Python 3吗?是的,这是一个bytearray,很抱歉键入了相同长度的ctypes数组类型,并将
bytearray
传递给它的构造函数,例如
L=len(MyData)
P=(ctypes.c_char*L)。来自缓冲区(MyData)
dll.FastProc(P,L)
。是的,谢谢eryksun,from\u buffer将允许c\u char数组与原始bytearray共享其字节。我一回到家就去考试。阅读进一步的文档,我还发现将C函数与Cython接口是另一种选择。我将尝试这两个选项并比较性能。我确认解决方案有效,并允许我的C例程在原始bytearray上正常工作(包括修改)。现在我需要尝试Python选项,我认为它更优雅(直接调用函数)且效率更高。嗯,乍一看我以为您已经找到了解决方案,但我去了create_string_buffer的文档,我的理解是它创建了一个新对象,并在其中XOPE了原始bytearray。这就是为什么最后打印的是新数据而不是mydata。到目前为止,我更希望我的函数在原始bytearray上工作,而不需要任何副本。ByteArray是可变的,不应该违反Python规则。我找到了推荐SWIG的帖子来实现我想要的,我需要深入研究。非常感谢您的帮助,我发现了create_string_buffer函数