Cython:外部结构定义引发编译器错误

时间:2019-01-27 08:21:52

标签: struct cython typedef

我正在尝试在Cython中使用Collections-C

我注意到abstract class Sensor { String getType(); } class CADPrototype extends Sensor { String getType() { return "Virtual"; } } class Accelerometer extends Sensor { String getType() { return "Real"; } } T foo<T extends Sensor>(T v1, T v2, T bar(T t1, T t2)) { if (v2 is CADPrototype) { return v1; } return v2; } Sensor foo_what_dart_does(Sensor v1, Sensor v2, Sensor bar(Sensor t1, Sensor t2)) { if (v2 is CADPrototype) { return v1; } return v2; } Accelerometer foo_infer_from_argument(Accelerometer v1, Accelerometer v2, Accelerometer bar(Accelerometer t1, Accelerometer t2)) { if (v2 is CADPrototype) { return v1; } return v2; } void main() { Accelerometer v1 = Accelerometer(); CADPrototype v2 = CADPrototype(); Sensor result; result = foo(v1, v2, (p1, p2) => p1); // it works result = foo_what_dart_does(v1, v2, (p1, p2) => p1); // Compilation Error: CADPrototype cannot be assigned to type Accelerometer result = foo_infer_from_argument(v1, v2, (p1, p2) => p1); } 文件中定义了一些结构,而.c文件中则定义了它们的别名。当我尝试在.h文件中定义这些结构并在.pxd文件中使用它们时,gcc会引发错误:.pyx

我能够将问题重现到最小的设置,该设置可以复制外部库和我的应用程序:

testdef.c

storage size of ‘[...]’ isn’t known

testdef.h

/* Note: I can't change this */
struct bogus_s {
    int x;
    int y;
};

cytestdef.pxd

/* Note: I can't change this */
typedef struct bogus_s Bogus;

cytestdef.pyx

# This is my code
cdef extern from 'testdef.h':
    struct bogus_s:
        int x
        int y

    ctypedef bogus_s Bogus

如果我运行cythonize,我会得到

# This is my code
def fn():
    cdef Bogus n

    n.x = 12
    n.y = 23

    print(n.x)

如果我使用Cython manual中的In function ‘__pyx_pf_7sandbox_9cytestdef_fn’: cytestdef.c:1106:9: error: storage size of ‘__pyx_v_n’ isn’t known Bogus __pyx_v_n; ^~~~~~~~~ 表示法,也会遇到相同的错误。

我在做什么错?

谢谢。

1 个答案:

答案 0 :(得分:1)

看看您的Collections-C库的文档,这些都是不透明的结构,您应该纯粹通过指针使用它们(不必知道有指针的大小,而在堆栈上进行分配的时候) 。这些结构的分配是在库函数中完成的。

要更改示例以匹配这种情况:

 // C file
 int bogus_s_new(struct bogus_s** v) {
     *v = malloc(sizeof(struct bogus_s));
     return (v!=NULL);
 }

 void free_bogus_s(struct bogus_s* v) {
      free(v);
 }

您的H文件将包含这些声明,而pxd文件将包含声明的包装。然后在Cython中:

def fn():
    cdef Bogus* n
    if not bogus_s_new(&n):
        return
    try:
        # you CANNOT access x and y since the type is
        # designed to be opaque. Instead you should use
        # the acessor functions defined in the header
        # n.x = 12
        # n.y = 23
    finally:
        free_bogus_s(n)