我有一个带动态分配数组的ctypes结构,即:
array_1d_double=npct.ndpointer(dtype=np.double,ndim=1,
flags='CONTIGUOUS')
class Test(Structure):
_fields_ = ("x", array_1d_double, ..)
test = Test()
do_some_init_in_c( for example malloc)
如果我打印test.x,我会得到以下输出:
<ndpointer_<f8_1d_CONTIGUOUS object at 0x7f104dc0c3b0>
c结构看起来大致如此,
structure Test_s{
double *x;....
};
如何像numpy数组一样访问这个元素? 是否可能需要将数组分配为np.arrays而不是使用malloc?这样做的正确方法是什么?
答案 0 :(得分:6)
你正在谈论的一种方法是直接在python端分配numpy数组,并且表现得像是C端的直接双数组。
import numpy as np
import ctypes as C
# allocate this as a normal numpy array with specified dtype
array_1d_double = np.array([1,2,3,4,5],dtype="float64")
# set the structure to contain a C double pointer
class Test(C.Structure):
_fields_ = [("x", C.POINTER(C.c_double))]
# Instantiate the structure so it can be passed to the C code
test = Test(np.ctypeslib.as_ctypes(array_1d_double))
# You can also do:
# test = Test()
# test.x = np.ctypeslib.as_ctypes(array_1d_double)
print test.x
# outputs: <__main__.LP_c_double object at 0x1014aa320>
您现在应该能够将结构的x
成员用作C代码中的普通双数组。
修改强>
澄清一下:如果您实例化一个没有参数的Structure
,它会为其所有成员提供NULL
个指针。
class Test(C.Structure):
_fields_ = [("x", C.POINTER(C.c_double)),
("y", C.POINTER(C.c_int))]
test = Test()
print test.x
# outputs: <__main__.LP_c_double object at 0x1014aa320>
print test.y
# outputs: <__main__.LP_c_int object at 0x101429320>
print test.x[0]
# raises ValueError: NULL pointer access
print test.y[0]
# raises ValueError: NULL pointer access
如果使用N个参数实例化Structure,那么这些参数将被分配给Structure的前N个成员。
test = Test(np.ctypeslib.as_ctypes(array_1d_double))
print text.x[0]
# outputs: 1.0
print test.y[0]
# raises ValueError: NULL pointer access
<强> EDIT2 强>
如果要将numpy数组永久绑定到结构,可以覆盖__init__
方法:
class MyDualArrayStruct(C.Structure):
_fields_ = [("c_x", C.POINTER(C.c_double)),
("c_y", C.POINTER(C.c_int))]
def __init__(self,*args,**kwargs):
super(MyDualArrayStruct,self).__init__(*args,**kwargs)
self.np_x = np.array([1,2,3,4,5],dtype="float64")
self.c_x = np.ctypeslib.as_ctypes(self.np_x)
self.np_y = np.array([5,4,3,2,1],dtype="int32")
self.c_y = np.ctypeslib.as_ctypes(self.np_y)
test = MyDualArrayStruct()
print test.np_x
print test.c_x[:5]
# Note that here c_x and np_x both contain the same data. Thus modifying one of them
# (inplace) modifies the other. You can use this to do easy inplace modification of
# numpy arrays in C functions.
# This implies that test.np_x.sum() is also the sum of test.c_x
test.np_x[:] = 1
print test.np_x
print test.c_x[:5]
输出:
[ 1. 2. 3. 4. 5.]
[1.0, 2.0, 3.0, 4.0, 5.0]
[ 1. 1. 1. 1. 1.]
[1.0, 1.0, 1.0, 1.0, 1.0]