简体   繁体   English

如何将结构内的 numpy 数组传递给 ctypes 函数?

[英]How to pass numpy array inside of struct to ctypes function?

I'm trying to wrap some third-party code from a library in my Python application.我正在尝试从我的 Python 应用程序中的库中包装一些第三方代码。 Essentially, the function I would like to call takes a struct as input that houses (among other things) pointers to double arrays.本质上,我想调用的函数将一个结构作为输入,其中包含(除其他外)指向双数组的指针。 A simplified example would be:一个简化的例子是:

myfunc.h: myfunc.h:

typedef struct mystruct_t {
    int n;
    double *x;
} mystruct_t;

double myfunc(mystruct_t* data);

myfunc.c : myfunc.c :

#include "myfunc.h"

double myfunc(mystruct_t* data) {
    double result = 0.;
    for(int i = 0; i < data->n; i++) {
        result += data->x[i];
    }
    return result;
}

Makefile :生成文件

CC = gcc
CFLAGS = -g -Wall -fPIC -lm -std=gnu99

all: libmyfunc.so

m.PHONY : clean

libmyfunc.so: myfunc.o
    gcc -shared -Wl,-soname,$@ -o $@ $^

%.o: %.c
    $(CC) -c $(CFLAGS) $<

clean:
    rm -vf libmyfunc.so *.o

I would like to wrap myfunc using NumPy, ctypes.Structure and numpy.ctypeslib so that I can pass NumPy arrays to myfunc as attributes of mystruct_t .我想使用 NumPy、 ctypes.Structurenumpy.ctypeslib包装myfunc ,以便我可以将 NumPy 数组作为mystruct_t属性传递给myfunc So far I've been trying the following:到目前为止,我一直在尝试以下方法:

myfunc.py: myfunc.py:

#!/usr/bin/env python
import numpy as np
import numpy.ctypeslib as npct
import ctypes
import os

array_1d_double = npct.ndpointer(dtype=np.double, ndim=1, flags='C_CONTIGUOUS')


class MyStruct(ctypes.Structure):
    _fields_ = [
        ('n', ctypes.c_int16),
        ('x', array_1d_double)
    ]

libmyfunc = npct.load_library('libmyfunc', os.path.dirname(__file__))
libmyfunc.myfunc.restype = ctypes.c_double
libmyfunc.myfunc.argtypes = [
    ctypes.POINTER(MyStruct)
]

x = np.array([1.0, 2.0, 3.0, 4.0])

mystruct = MyStruct()
mystruct.n = len(x)
mystruct.x = x

res = libmyfunc.myfunc(mystruct)

However, this fails with the following error message:但是,这失败并显示以下错误消息:

$ python myfunc.py
Traceback (most recent call last):
  File "./myfunc.py", line 26, in <module>
    mystruct.x = x
TypeError: cannot be converted to pointer

How do I define my function signatures correctly so that type conversion can happen?如何正确定义函数签名以便进行类型转换? Or do I need to convert x somehow before assigning it to mystruct.x ?或者我是否需要在将x分配给mystruct.x之前以某种方式转换它?

Unfortunately I cannot change the signature of the method I would like to call and I would like to not have to write wrapper C code unless it is absolutely necessary.不幸的是,我无法更改要调用的方法的签名,并且除非绝对必要,否则我不想编写包装器 C 代码。 The other questions and resources that I've found on this only deal with either ctypes.Structure s or numpy.ctypeslib , but can you make them work together?我在这方面发现的其他问题和资源仅涉及ctypes.Structure s 或numpy.ctypeslib ,但你能让它们一起工作吗?

I've uploaded my reduced example as a gist so you can use it as a starting point.我已经上传了我的简化示例作为要点,因此您可以将其用作起点。

Many thanks in advance!提前谢谢了!

You can remove array_1d_double .您可以删除array_1d_double It is not needed.不需要。

The struct should be declared like this:该结构应声明如下:

class MyStruct(ctypes.Structure):
    _fields_ = [
        ('n', ctypes.c_int),
        ('x', ctypes.POINTER(ctypes.c_double))
    ]

I've changed both types.我已经改变了两种类型。 You had c_int16 , but the type you used in the C code is int .您有c_int16 ,但您在 C 代码中使用的类型是int That maps to c_int .那映射到c_int And likewise for the array, that is double* .同样对于数组,那是double* In ctypes that is POINTER(ctypes.c_double) .在 ctypes 中是POINTER(ctypes.c_double)

The struct should be initialised like this:该结构应该像这样初始化:

mystruct = MyStruct()
mystruct.n = len(x)
mystruct.x = npct.as_ctypes(x)

With these changes, your code works as intended.通过这些更改,您的代码可以按预期工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM