6

我正在尝试使用一个 C 库,它使用回调函数(callback_function)来提供指向我想要包装的结构(glp_tree)的指针。

使用未在其中创建的指针初始化实例的正确方法是什么__cinit__?我在 cython 文档中找不到这种模式的示例。

我有一些工作代码(见下文),它将指针转换为整数并返回,但我不确定这是一个好的做法/理智。

cdef extern from "stdint.h":
    ctypedef unsigned long long uint64_t

cdef extern from "glpk.h":
    ctypedef struct glp_tree:
        pass

cdef void callback_func(glp_tree* tree, void *info):
    treeobj = Tree(<uint64_t>tree) // cast to an integer...

cdef class Tree:
    cdef glp_tree* ptr
    def __init__(self, uint64_t ptr):
        self.ptr = <glp_tree*>ptr // ... and back to a pointer

直接传递 glp_tree 对象似乎可行(尽管这不是我想要做的),但尝试传递指针会导致编译器错误:

Cannot convert 'glp_tree *' to Python object
4

3 回答 3

7

您可以使用自定义来创建实例,而不是使用__init__/ (它总是期望 Python 对象作为参数):__cinit__@staticmethod cdef

cdef class Tree:
    cdef glp_tree* ptr

    def __init__(self, *args):
        raise TypeError('Cannot create instance from Python')

    @staticmethod
    cdef Tree create(glp_tree* ptr):
        obj = <Tree>Tree.__new__(Tree) # create instance without calling __init__
        obj.ptr = ptr
        return obj
于 2017-01-18T10:30:24.570 回答
2

将指针转换为整数是一种选择,但正确使用的类型是uintptr_t,而不是uint64_t(它是自记录的,并且始终具有适合平台的宽度)。

问题是构造 aTree是一个 Python 操作,您可以在cython -a输出中清楚地看到。构造函数的输入必须转换为 Python 数据结构,而指针没有明显的转换。

于 2013-09-09T10:06:11.493 回答
-1

这将起作用

cdef class Tree:
    cdef glp_tree* ptr
    def __init__(self, long ptr):
        self.ptr = <glp_tree*>PyLong_AsVoidPtr(ptr)
于 2015-01-03T11:56:49.940 回答