我有一个 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;
}
这个answer似乎是说将创建的数组从 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]
但是,当我运行 python 包装器时,代码在 ptr[:size]
处静默失败好像我正在尝试越界访问数组,我可能是,但是传递这个动态大小数组的正确方法是什么?
最佳答案
几点考虑:
首先,您需要正确设置 C 函数的原型(prototype),以便 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
关于python - 如何包装一个 C 函数,该函数返回一个指向带有 ctypes 的 malloc 数组的指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63540036/