我既没有C++的经验,也没有ctypes库的经验。
我有一个用C语言编写的程序,其中包含一个名为image_lib
的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中,我有一个名为x_spots
的数组和其他一些数组:
# coordinate locations
x_spots = np.arange(-1, 2, 1, dtype=float)
x_spots = np.arange(-1, 2, 1, dtype=float)
z_spots = np.arange([0] * num_tweezers.value, dtype=float)
# Intensities
int_spots = np.arange([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');
我有(基于制造商给出的单一例子)
image_lib.Generate_Hologram(Image.ctpyes.data_as(POINTER(c_ubyte)), WFC.ctypes.data_as(POINTER(c_ubyte)), ....
)
我怎么把x_floats传递给这个函数呢?
x_spots.ctypes.data_as(POINTER(c_float))
2条答案
按热度按时间rekjcdws1#
我能在代码中发现的一个问题是浮点数的大小。
注意,作为一个指针,你传递给函数的numpy数据的指针并不重要,比如我,我习惯于以
arr.ctypes.data_as(ctypes.c_void_p)
的形式传递数据。这是动态的,所以C编译器不可能检查任何东西,而且,至少在这个例子中,没有动态检查,也没有意义把这个numpy数组数据当作指向这个类型的指针。
因此,正确地或不正确地说,作为POINTER,你想传递一个numpy数组给一个函数,期望一个浮点数 *,并不能保护你免受错误。
这也不意味着任何转换,指针只是传递给C函数,由它来正确解释,这是静态完成的,当你输入参数
float *
时。因此,在代码中(你似乎很想知道),你不能确保C函数得到它所期望的一堆
float
,不管怎样,C函数将得到一个指向numpy数据的指针。代码中的问题是
x_spots
中的数据不是float
(如单词float
的C含义;即32位浮点数)。它们很可能是双精度数我说“最有可能”是因为我不是不同python解释器的Maven,我知道,根据解释器的不同,原生
float
类型的python可能是float32
,或者float64
,甚至是其他类型的,在最经典的CPython中,它们是float64
。我也不确定当dtypes
是原生类型float
时,对numpy意味着什么。但是,使用我的cpython,一个np.array([1,2,3], dtype=float)
是一个由float64
组成的numpy数组。所以,不是100%确定这是否是一个确定的事情,或者是否存在一个python解释器,在其中该数组将由float32
组成。因为我不确定,无论如何,我从来不用float
作为dtype
的参数,我用np.float32
或np.float64
。但是,最有可能(甚至可以肯定)您的
x_spots
是由float64
组成的。然后,当你传递
x_spots.ctypes.data_as(POINTER(...))
时,你所说的指针是什么并不重要,指针将是指向那些float64
的指针。也就是说,用C语言来说,指向double
。你的C函数将把它当作指向float
的指针(没有任何警告:警告发生在编译时,我们已经过去了)。说来话长但结论是要么你
double *
作为参数,对于你的,可能是64位的计算机,这可能是最好的方法,但是你好像说你不能修改C函数float
(C语言的意思)组成,即使用dtype=np.float32
创建x_spots
。请注意,即使您选择第一种情况(
double *
),也最好将dtype更改为显式设置为np.float64
。一旦你这样做了,不管你是以
x_spots.ctypes.data_as(c_void_p)
,x_spots.ctypes.data_as(POINTER(c_float))
,x_spots.ctypes.data_as(POINTER(c_double))
,甚至x_spots.ctypes.data_as(POINTER(c_char))
的形式传递参数。(当然,我强烈建议您不要使用错误类型
POINTER()
arg,但这是为了代码的可读性;从执行变更的Angular 来看,它不会改变结果)所以
float *
更改为double *
dtype
从float
更改为np.float32
mec1mxoz2#
下面是一个使用
numpy
将Cfloat
作为参数传递的最小示例。这是OP将其应用于其函数的练习。注意,C函数必须假定为固定大小,或者以某种形式传递数组的长度。还要注意,
dtype
被声明为ct.c_float
,因为Pythonfloat
通常是64位的,而Cfloat
通常是32位的。输出: