ラップしたいライブラリのヘッダーファイルに次のマクロがあります。
#define RB_ROOT (struct rb_root) { NULL, }
RB_ROOTマクロは、CコードでNULLを使用してルートノードを初期化するために使用されているようです。これはどのようにrb_root
見えるかです:
struct rb_root {
struct rb_node *rb_node;
};
Cythonでrb_rootを初期化したい。これは、それを作成してNULLに設定する必要があることを意味します。
私が試してみました
self.root = ckerneltree.rb_root(node=NULL)
しかし、これは私にエラーを与えます
cdef ckerneltree.rb_root root
cdef ckerneltree.rb_node node
def __cinit__(self):
self.root = ckerneltree.rb_root(node=NULL)
^
------------------------------------------------------------
kerneltree.pyx:10:45: Cannot assign type 'void *' to 'rb_node'
そして私がそのようにkwargを取り除くならば
self.root = ckerneltree.rb_root()
厄介なCコンパイラの警告が表示されます。
kerneltree.c: In function '__pyx_tp_new_10kerneltree_IntervalTree':
kerneltree.c:1100:22: warning: '__pyx_t_1.rb_node' may be used uninitialized in this function [-Wmaybe-uninitialized]
__pyx_v_self->root = __pyx_t_1;
^
kerneltree.c:1090:18: note: '__pyx_t_1.rb_node' was declared here
struct rb_root __pyx_t_1;
^
それを行う正しい方法は何ですか?
追伸 これは私の.pxdがどのように見えるかです:
cdef extern from "src/rbtree.h":
cdef struct rb_node:
pass
cdef struct rb_root:
rb_node node
私の.pyx:
cimport ckerneltree
cdef class IntervalTree:
cdef ckerneltree.rb_root root
def __cinit__(self):
self.root = ckerneltree.rb_root()
意外かもしれませんが、あなたの場合self.rb_root.node
はすでにに設定されていNULL
ます。ただし、NULL
明示的に設定する場合は、次のようにすることができます。
cdef class IntervalTree:
cdef ckerneltree.rb_root root
def __cinit__(self):
self.root.rb_root = NULL # setting pointer to NULL explicitly
これは、すべてが参照であるが、オブジェクトroot
へのrb_root
ポインターではなく、オブジェクト自体であるPythonコーダーにとっては直感に反する可能性があります。これはIntervalTree
、Cコードでのcdefクラスの定義がどのように見えるかです。
struct __pyx_obj_4test_IntervalTree {
PyObject_HEAD
struct rb_root root;
};
ご覧のとおり、はとして定義されてrb_root
おり、ではありませんrb_root *
。IntervalTree
-objectのメモリレイアウトは非常に単純です。
+-------------------+ +--------------------+
| PyObject | | rb_root |
+-------------------+ +--------------------+
| Py-Obect members | | rb_node |
+-------------------+ +--------------------+
| ?? bytes | | 8 bytes |
+-------------------+ +--------------------+
Pythonオブジェクトのデフォルトの初期化__cinit()__
は、実行される前に開始され、オブジェクトのメモリ全体が0
sに設定されるため、(-objectへのrb_node
ポインタであるrb_node
)の8バイトの値0
はと同じになりNULL
ます。ただし、明示的に初期化しても害はありません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加