使用Cython将结构从C返回到Python

Red*_*ing 4 c python struct cython

我正在尝试将结构从ac文件传递回我的Python中。假设我有一个文件pointc.c像这样:

typedef struct Point {
    int x;
    int y;
} Point;

struct Point make_and_send_point(int x, int y);

struct Point make_and_send_point(int x, int y) {
    struct Point p = {x, y};
    return p;
}
Run Code Online (Sandbox Code Playgroud)

然后,我像这样设置一个point.pyx文件:

"# distutils: language = c"
# distutils: sources = pointc.c

cdef struct Point:
    int x
    int y

cdef extern from "pointc.c":
    Point make_and_send_point(int x, int y)

def make_point(int x, int y):
    return make_and_send_point(x, y) // This won't work, but compiles without the 'return' in-front of the function call
Run Code Online (Sandbox Code Playgroud)

如何将返回的结构放入Python?只有通过在Cython中创建一个结构并通过引用void c函数进行发送,这种事情才能实现吗?

作为参考,我的setup.py是:

from distutils.core import setup, Extension
from Cython.Build import cythonize

setup(ext_modules = cythonize(
      "point.pyx",
      language="c"
     )
)
Run Code Online (Sandbox Code Playgroud)

chr*_*isb 5

最典型的是,您将编写某种包含c级结构的包装器类,例如:

# point.pyx
cdef extern from "pointc.c":
    ctypedef struct Point:
        int x
        int y
    Point make_and_send_point(int x, int y)

cdef class PyPoint:
    cdef Point p

    def __init__(self, x, y):
        self.p = make_and_send_point(x, y)

    @property
    def x(self):
       return self.p.x

    @property
    def y(self):
        return self.p.y
Run Code Online (Sandbox Code Playgroud)

使用中

>>> import point
>>> p = point.PyPoint(10, 10)
>>> p.x
10
Run Code Online (Sandbox Code Playgroud)


Dav*_*idW 5

Cython 给定结构的默认行为是将其转换为 Python 字典,这对您来说可能已经足够了。(这仅适用于由简单类型组成的结构)。

这不起作用有几个原因。首先,您应该cdef extern fromheaders 开始,而不是源文件,否则您会收到有关多个定义的错误(我认为这只是创建最小示例时的错误)。其次,您需要将 的定义Point放在cdef extern块中:

cdef extern from "pointc.h":
    cdef struct Point:
        int x
        int y
Run Code Online (Sandbox Code Playgroud)

如果你不这样做,那么 Cython 会为你的结构创建一个错位的内部名称(__pyx_t_5point_Point )该与 C 函数签名不匹配,因此它会失败。

更正后,您将获得将结构转换为字典的正确默认行为。(这应该是双向的 - 您可以将 dicts 转换回结构体)。如果这不是您想要的,请按照@chrisb 的回答进行操作