c-使用类型和@cdecl从Swift向Python发送大量字节



我有两个简单的函数,一个传递给另一个UInt数组。当我通过20个UInts的小数组时,函数有效,但当我通过21576个UInts函数返回少量bits时,为什么会发生这种情况?

我检查了里面的UnsafeMutablePointer<UInt8>是否有正确的数字,但在Python方面,它们丢失了。

Swift:

@_cdecl("getPointer")
public func getPointer() -> UnsafeMutablePointer<UInt8>{
let arr: Array<UInt8> =[1,2,3.....] //here is big array
if let buffer = buffer {
buffer.deallocate()
buffer.deinitialize(count: arr.count)
}
buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: arr.count * MemoryLayout<UInt8>.stride)
buffer!.initialize(from: arr, count: arr.count) 

return buffer!
}

Python:

native_lib = ctypes.CDLL('./libH264_decoder')
native_lib.getPointer.restype = ndpointer(dtype=ctypes.c_uint8)
cont = cast(native_lib.getPointer(), c_char_p).value

返回b'x1crix1aVLxa4qxfcxa7xaezbx83HCx94xb4#xde?xxdbxb1xd3x1dx07xb5@xc8x85x0ePxaax9ewx03x93xfe8xa6x97Dxcaxc6xcc'

我不知道Swift,但要将包含null的数据缓冲区返回给ctypes,您需要知道缓冲区的大小,并且不能使用c_char_p作为返回类型,因为ctypes假定以null结尾的数据,并将该特定类型转换为bytes对象。对于可以包含null的任意数据,请改用POINTER(c_char)

下面我制作了一个简单的C DLL,它返回一个指向某些数据的指针,并在一个额外的输出参数中返回大小。同样的技术应该适用于Swift,假设它使用标准的C ABI来导出函数,但如果大小是可变的,则需要同时返回指针和大小。

测试.c

__declspec(dllexport)
char* get_data(int* size) {
*size = 8;
return "x11x22x00x33x44x00x55x66";
}

测试.py

import ctypes as ct
dll = ct.CDLL('./test')
dll.get_data.argtypes = ct.POINTER(ct.c_int),  
dll.get_data.restype = ct.POINTER(ct.c_char)   # do NOT use ct.c_char_p
size = ct.c_int()  # allocate ctypes storage for the output parameter.
buf = dll.get_data(ct.byref(size))  # pass by reference.
print(buf[:size.value].hex(' '))    # Use string slicing to control the size.
# .hex(' ') for pretty-printing the data.

输出:

11 22 00 33 44 00 55 66

在python调用程序站点上,将返回的数组强制转换为"字符指针";,其期望被NULL终止。如果你的数组中没有任何二进制零,你可以检查以下内容(这里只有重要部分(:

var arr: Array<UInt8> = [] //here is big array

for _ in 0..<100 {
for i in 0..<26 {
arr.append(UInt8(65+i)) // A...Z
}
}
arr.append(0) // Terminate C-String alike with binary Zero
buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: arr.count * MemoryLayout<UInt8>.stride)
buffer!.initialize(from: arr, count: arr.count) 

return buffer!

最新更新