Cython无符号字符uuid_t [16]表示 [英] Cython unsigned char uuid_t[16] representaion
问题描述
我的代码中有结构声明:
I have structure declarations in my code:
cdef extern from "uuid/uuid.h":
ctypedef unsigned char uuid_t[16]
cdef extern from "fr_common.h":
ctypedef uuid_t fr_id_t
ctypedef struct fr_event_t:
fr_id_t id
size_t action
fr_id_t object_id
long long ts
这里有cython类我需要从 fr_event_t
结构传递 fr_id_t id
值。
Here I have cython class where I need to pass fr_id_t id
value from fr_event_t
structure.
cdef class Event:
cdef:
bytes _id
int _action
bytes object_id
int _ts
def __cinit__(self, fr_id_t id, int action, fr_id_t object_id, int ts):
self._id = id
self._action = action
self._object_id = object_id
self._ts = ts
@staticmethod
cdef Event from_c(fr_event_t fr_event):
return Event(
fr_id_t=fr_event.id,
action=fr_event.action,
object_id=fr_event.object_id,
ts=fr_event.ts,
我如何表示 fr_id_t
类型以其他方式传递给函数?它的表示形式是 unsigned char uuid_t [16]
,用于存储字节。传递 fr_id_t
不起作用,cython编译器在将我的.pyx文件编译成.so时给了我断言错误。
How I can represent fr_id_t
type passing it in the function somehow else? Its representation is unsigned char uuid_t[16]
that stores bytes. Passing fr_id_t
is not working and cython compiler gives me assertion error while compiling my .pyx file into .so.
AssertionError: (<FileSourceDescriptor:/home/dmitriyravdel/teyefr/teye-fr/python/teyefr/_teyefr.pyx>, 356, 24): (__pyx_v_id == ((unsigned char *)NULL)) && PyErr_Occurred()
推荐答案
错误消息是Cython中的错误很难诊断。但是,您尝试执行的操作对我来说并没有太大意义。
The error message is a bug in Cython an makes it pretty hard to diagnose. However, what you're trying to do doesn't make a lot of sense to me.
__ init __
和 __ cinit __
基本上是Python方法,它们的参数必须是Python对象
__init__
and __cinit__
are fundamentally Python methods and their arguments must be Python objects
所有构造函数参数都将作为Python对象传递。这意味着不能将不可转换的C类型(例如指针或C ++对象)从Cython代码传递到构造函数中。如果需要,请使用工厂函数来处理对象初始化。在此函数中直接调用
__ new __()
通常有助于绕过对__ init __()
构造函数的调用。 / p>
All constructor arguments will be passed as Python objects. This implies that non-convertible C types such as pointers or C++ objects cannot be passed into the constructor from Cython code. If this is needed, use a factory function instead that handles the object initialisation. It often helps to directly call
__new__()
in this function to bypass the call to the__init__()
constructor.
将发生的情况(如果您的代码有效)是将第一个 fr_event.id
转换为将传递给 __ cinit __
然后的Python对象,它将转换回 fr_id_t
,然后然后将其转换为存储它的 bytes
个字节。 这不是您想要的!,这些转换之一似乎使Cython感到困惑。
What will happen (if your code worked) is that first fr_event.id
will be converted to a Python object to be passed to __cinit__
then it'll be converted back to a fr_id_t
, then it'll be converted to a bytes
where you store it. This is not what you want! It looks like one of these conversions has confused Cython.
您真正想做的是创建一个真正为空的事件
在 from_c
中:
What you actually want to do is to create a genuinely empty Event
in from_c
:
@staticmethod
cdef from_c(fr_event_t event):
cdef Event e = Event.__new__() # This only works if __cinit__ is removed or takes no arguments
e._id = event.id
# etc
return e
您也不能拥有 fr_id_t
__ cinit __
的参数,因为它们触发了问题。我建议从Python(仅Cython)构造 Event
对象没有任何意义,因此您可能不应该使用 __ cinit __
。另一种选择是使用 __ cinit __
接受与Python等价的类型 bytes
和 int
:
You also cannot have fr_id_t
arguments to __cinit__
since these are what triggers the issue. I'd suggest that it isn't meaningful to construct Event
objects from Python (only Cython) so that you probably shouldn't have a __cinit__
at all. Another alternative would be to have a __cinit__
that takes the Python equivalent types bytes
and int
:
cdef class Event:
cdef bytes _id
def __cinit__(self, bytes id):
self._id = id
@staticmethod
cdef from_c(fr_event_t event):
return Event(event.id)
(为简单起见,我进一步简化了此示例)
(I've cut this example down further for the sake of simplicity)
这篇关于Cython无符号字符uuid_t [16]表示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!