我有一个 C 函数,它读取一个二进制文件并返回一个动态大小的无符号整数数组(大小基于二进制文件的元数据):
//example.c
#include <stdio.h>
#include <stdlib.h>
__declspec(dllexport)unsigned int *read_data(char *filename, size_t* array_size){
FILE *f = fopen(filename, "rb");
fread(array_size, sizeof(size_t), 1, f);
unsigned int *array = (unsigned int *)malloc(*array_size * sizeof(unsigned int));
fread(array, sizeof(unsigned int), *array_size, f);
fclose(f);
return array;
}
Run Code Online (Sandbox Code Playgroud)
这个答案似乎是说将创建的数组从 C 传递到 Python 的正确方法是这样的:
# example_wrap.py
from ctypes import *
import os
os.add_dll_directory(os.getcwd())
indexer_dll = CDLL("example.dll")
def read_data(filename):
filename = bytes(filename, 'utf-8')
size = c_size_t()
ptr = indexer_dll.read_data(filename, byref(size))
return ptr[:size]
Run Code Online (Sandbox Code Playgroud)
但是,当我运行 python 包装器时,代码默默地失败了,ptr[:size]就好像我试图越界访问数组一样,我可能是,但是传递这个动态大小数组的正确方法是什么?
一些注意事项:
首先,您需要正确设置C函数的原型,以便ctypes能够在C和Python类型之间正确转换。
其次,由于size它实际上是一个ctypes.c_size_t对象,因此您实际上需要使用它size.value来访问数组大小的数值。
第三,由于ptr[:size.value]实际上将数组内容复制到 Python 列表中,因此您需要确保也free()分配了分配的 C 数组,因为您将不再使用它。
(也许将数组复制到 Python 列表在这里并不理想,但我假设这里没问题,因为否则在 Python 中处理 C 数组会更加复杂。)
这应该有效:
from ctypes import *
import os
os.add_dll_directory(os.getcwd())
indexer_dll = CDLL("example.dll")
indexer_dll.read_data.argtypes = [c_char_p, POINTER(c_size_t)
indexer_dll.read_data.restype = POINTER(c_int)
libc = cdll.msvcrt
def read_data(filename):
filename = bytes(filename, 'utf-8')
size = c_size_t()
ptr = indexer_dll.read_data(filename, byref(size))
result = ptr[:size.value]
libc.free(ptr)
return result
Run Code Online (Sandbox Code Playgroud)