我正在尝试使用一个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
答案 0 :(得分:4)
您可以使用自定义__init__
来创建实例,而不是使用__cinit__
/ @staticmethod cdef
(它总是希望Python对象作为参数):
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
答案 1 :(得分:2)
投射指向整数的指针是一个选项,但是要使用的正确类型是uintptr_t
,而不是uint64_t
(它是自我记录的,并且总是具有适合平台的宽度)。 / p>
问题是构造Tree
是一个Python操作,您可以在cython -a
输出中清楚地看到。构造函数的输入必须转换为Python数据结构,而指针没有明显的转换。
答案 2 :(得分:-1)
这将有效
cdef class Tree:
cdef glp_tree* ptr
def __init__(self, long ptr):
self.ptr = <glp_tree*>PyLong_AsVoidPtr(ptr)