我希望能够将结构传递给某些 C 代码,并且正在使用 ctypes.struct。我有一个简单的工作示例,它采用输入数组并对元素进行平方并将输出作为数组。但是,我在将其放入 python 类中以创建包装器例程时遇到问题。
简单的c代码是:
测试.c
struct DATA;
typedef struct DATA {
int n;
double *ina;
double *outa;
} DATA;
void square_array2(DATA *data) {
int i;
for (i=0; i<data->n; i++) {
data->outa[i] = data->ina[i]*data->ina[i];
}
}
我用
编译这个gcc -shared -fPIC test.c -o test.so
在 jupyter 笔记本中我有:
import importlib
import numpy as np
import ctypes
from ctypes import CDLL, POINTER
from ctypes import c_size_t, c_double
from wurlitzer import pipes, STDOUT
%reload_ext wurlitzer
testlib = CDLL('test.so')
n=5
ina = np.linspace(1.0,5.0,n)
outa = np.zeros(n,np.float64)
class Data(ctypes.Structure):
_fields_ = [("n", ctypes.c_int),
("ina", ctypes.POINTER(ctypes.c_double)),
("outa", ctypes.POINTER(ctypes.c_double))]
data = Data(n,np.ctypeslib.as_ctypes(ina),np.ctypeslib.as_ctypes(outa))
print("initial array",ina)
testlib.square_array2.restype = None
testlib.square_array2(ctypes.byref(data))
print("final array",outa)
这一切在 jupyter 笔记本中都可以正常工作。
不起作用的部分是把这个 进入 python 类包装器。
这是我的包装尝试,但不起作用:
import ctypes
from ctypes import CDLL, POINTER
from ctypes import c_size_t, c_double, c_int
from io import StringIO
from wurlitzer import pipes, STDOUT
class Data(ctypes.Structure):
_fields_ = [("n", ctypes.c_int),
("ina", ctypes.POINTER(ctypes.c_double)),
("outa", ctypes.POINTER(ctypes.c_double))]
class testClib(Data): #attempting to inherit the Data class.
def __init__(self):
# load the library
self.lib = CDLL("test.so")
def square_array2(self,ina,outa):
n, = ina.shape
# !!! the line that doesn't work....
data = Data(n,np.ctypeslib.as_ctypes(ina),np.ctypeslib.as_ctypes(outa))
out = StringIO()
with pipes(stdout=out, stderr=STDOUT):
self.lib.square_array2.restype = None
self.lib.square_array2(ctypes.byref(data))
stdout = out.getvalue()
print(stdout)
print(ina)
print(outa)
我使用以下命令从我的 jupyter 笔记本中调用此例程:
ctest.square_array2(ina,outa)
执行时的错误信息是:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[51], line 3
1 # lets add this in a wrapper routine
----> 3 ctest.square_array2(ina,outa)
File ~/WORK/PYTHONLIB/ctypesTEST/ctypesTEST3.py:46, in testClib.square_array2(self, ina, outa)
42 def square_array2(self,ina,outa):
44 n, = ina.shape
---> 46 data = Data(n,np.ctypeslib.as_ctypes(ina),np.ctypeslib.as_ctypes(outa))
48 out = StringIO()
50 with pipes(stdout=out, stderr=STDOUT):
TypeError: too many initializers
在创建我的问题的更简单版本时,我想我找到了答案。 在我的 jupyter 笔记本中,我有以下内容。
import numpy as np
import ctypes
# link to the python wrapper library
import ctypesTEST4 as ct
下一个块是第一个始终有效的测试:
# Example 1 -- sending a structure in the python code
# set up an in and out array
n=5
ina = np.linspace(1.0,5.0,n)
outa = np.zeros(n,np.float64)
# link to the c-library
testlib = ctypes.CDLL('test.4.so')
# set the data structure
class Data(ctypes.Structure):
_fields_ = [("n", ctypes.c_int),
("ina", ctypes.POINTER(ctypes.c_double)),
("outa", ctypes.POINTER(ctypes.c_double))]
data = Data(n, np.ctypeslib.as_ctypes(ina), np.ctypeslib.as_ctypes(outa))
testlib.square_array.restype = None
testlib.square_array(ctypes.byref(data))
print("initial array",ina)
print(" final array",outa)
这会生成答案
初始数组[1. 2.3.4.5.] 最终数组 [1.4.9.16.25.]
下一个块是现在有效的测试......
在 jupyter 中我有块:
# create an instance of the class
ctest = ct.testClib()
ctest.square_array(ina,outa)
print("initial array",ina)
print(" final array",outa)
import numpy as np
import ctypes
class Data(ctypes.Structure):
_fields_ = [("n", ctypes.c_int),
("ina", ctypes.POINTER(ctypes.c_double)),
("outa", ctypes.POINTER(ctypes.c_double))]
class testClib():
def __init__(self):
# load the library
self.lib = ctypes.CDLL("test.4.so")
def square_array(self,ina,outa):
n, = ina.shape
data = Data(n,np.ctypeslib.as_ctypes(ina),np.ctypeslib.as_ctypes(outa))
self.lib.square_array.restype = None
self.lib.square_array(ctypes.byref(data))
c 代码看起来像这样
struct DATA;
typedef struct DATA
{
int n;
double *ina;
double *outa;
} DATA;
void square_array(DATA *data)
{
int i;
for (i=0; i<data->n; i++)
{
data->outa[i] = data->ina[i]*data->ina[i];
}
}
我再次编译了
gcc -shared -fPIC test.4.c -o test.4.so
这是调用Python包装库