如何通过ctypes将Python浮点数组传入C DLL函数?
问题:如何用ctypes将numpy浮点数组传入C DLL函数?
本人既无C++开发经验,也不了解ctypes库。现有一个名为image_lib的C语言编写的DLL,其头文件中定义了函数:
int Generate_Hologram(unsigned char *Array, unsigned char* WFC, float *x_spots, float *y_spots, float *z_spots, float *I_spots, int N_spots, int ApplyAffine);
在Python中,我已创建了如下numpy数组:
# coordinate locations x_spots = np.arange(-1, 2, 1, dtype=float) y_spots = np.arange(-1, 2, 1, dtype=float) z_spots = np.array([0] * num_tweezers.value, dtype=float) # Intensities int_spots = np.array([1] * num_tweezers.value, dtype=float) # Image for the GPU to compute the hologram on Image = np.empty([width.value*height.value*bytpesPerPixel], np.uint8, 'C'); # Create a blank vector to hold the wavefront correction WFC = np.empty([width.value*height.value*bytpesPerPixel], np.uint8, 'C');
(注:原代码中x_spots重复定义、z_spots和int_spots用arange的写法有误,已修正为array)
根据厂商提供的示例,我已知道如何传入uint8类型数组:
image_lib.Generate_Hologram(Image.ctypes.data_as(POINTER(c_ubyte)), WFC.ctypes.data_as(POINTER(c_ubyte)), .... )
请问如何将x_spots这类浮点数组传入该函数?我猜测的写法是:
x_spots.ctypes.data_as(POINTER(c_float))
解答
你的猜测完全正确,但需要注意两个关键细节,避免出现内存不匹配的问题:
确保numpy数组的 dtype 与 C 的 float 匹配
C语言中的float是32位单精度浮点数,对应numpy的np.float32。如果你创建数组时用的是默认的np.float(即64位双精度),必须先转换类型:x_spots = x_spots.astype(np.float32) y_spots = y_spots.astype(np.float32) z_spots = z_spots.astype(np.float32) int_spots = int_spots.astype(np.float32)保证数组是C连续内存布局
你创建数组时已经指定了'C'参数,这符合C语言的内存顺序要求。如果后续对数组做了切片、转置等操作,可能会破坏这个布局,此时需要用np.ascontiguousarray()重新整理:x_spots = np.ascontiguousarray(x_spots, dtype=np.float32)
完整调用示例
from ctypes import POINTER, c_ubyte, c_float, c_int import numpy as np # 假设已经加载了image_lib,比如: # import ctypes # image_lib = ctypes.CDLL("path/to/image_lib.dll") # 修正并转换数组类型 x_spots = np.arange(-1, 2, 1, dtype=np.float32) y_spots = np.arange(-1, 2, 1, dtype=np.float32) z_spots = np.array([0] * num_tweezers.value, dtype=np.float32) int_spots = np.array([1] * num_tweezers.value, dtype=np.float32) # 调用函数 result = image_lib.Generate_Hologram( Image.ctypes.data_as(POINTER(c_ubyte)), WFC.ctypes.data_as(POINTER(c_ubyte)), x_spots.ctypes.data_as(POINTER(c_float)), y_spots.ctypes.data_as(POINTER(c_float)), z_spots.ctypes.data_as(POINTER(c_float)), int_spots.ctypes.data_as(POINTER(c_float)), c_int(len(x_spots)), # N_spots是点的数量,对应数组长度 c_int(0) # ApplyAffine根据需求传0或1 )
内容的提问来源于stack exchange,提问作者LionCereals
相关产品推荐
相关产品推荐

