将 ctypes.Structure 包装在类中

问题描述 投票:0回答:1

我希望能够将结构传递给某些 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
python c structure ctypes wrapper
1个回答
0
投票

在创建我的问题的更简单版本时,我想我找到了答案。 在我的 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 中我有块:

示例 2——使用包装例程来做同样的事情

# 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包装库

© www.soinside.com 2019 - 2024. All rights reserved.