从另一个对象访问结构指针时遇到问题

时间:2017-12-20 15:35:00

标签: python cython

foo.h中

typedef int bar;
typedef struct _foo
{
    bar* b;
} foo;
extern foo* foo_new();
extern bar* foo_bar_new(foo* f);

foo.pxd

cdef extern from "foo.h":
    ctypedef int bar;
    ctypedef struct foo:
        bar* b
    foo* foo_new();
    bar* foo_bar_new(foo* f);

foo.pyx

from foo cimport *

cdef class Foo:
    cdef foo* _ptr
    def __cinit__(self):
        self._ptr = foo_new()

cdef class Bar:
    cdef bar* _ptr
    def __cinit__(self, f):
        self._ptr = foo_bar_new(f._ptr)   # error
                                ^
foo.pyx:11:33: Cannot convert Python object to 'foo *'

cython foo.pyx在标记的行处抛出错误。

我不太确定我做错了什么。将_ptr中的Foo更改为cpdef会导致相同的错误。

==更新== 我将 foo.pyx 更改为以下内容并且有效。

from foo cimport *

cdef class Foo:
    cdef foo* _ptr
    def __cinit__(self):
        self._ptr = foo_new()

    def new_bar(self):
        cdef bar* b
        b = foo_bar_new(self._ptr)
        tmp = Bar()
        tmp._set(b)
        return tmp

cdef class Bar:
    cdef bar* _ptr
    cdef _set(self, bar* bptr):
        self._ptr = bptr

    def get(self):
        return bar_get(self._ptr)

我可以做f=Foo(); b=f.new_bar()但这对我来说似乎并不理想,因为我无法使用Bar(f)或类似内容创建。问题在于我不能cdef __cinit__(),因为它是一种特殊的方法。也不能cdef __init__()。关于如何解决这个问题的任何想法?

2 个答案:

答案 0 :(得分:1)

您需要确保在编译时知道BasePoint的类型:

f

没有这样做,它必须假设def __cinit__(self, Foo f): self._ptr = foo_bar_new(f._ptr) # error 是标准的Python属性查找(在运行时完成),因此将是一个标准的Python对象。如果您指定_ptrf,那么它就可以使用Foo的已知定义。

答案 1 :(得分:0)

我一直在使用似乎正常工作的工厂功能模型的修改。

cdef class Bar:
    cdef bar* _ptr
    def __cinit__(self):
        self._ptr = NULL

    cdef from_ptr(self, bar* ptr):
        self._ptr = ptr
        return self

cdef class Foo:
    cdef foo* _ptr
    def new_bar(self):
        cdef bar* b
        b = foo_bar_new(self._ptr)
        return Bar().from_ptr(b)