0

We have given Cython code:

cdef extern from "C_File_A.h": cdef struct C_Obj_A: pass cdef extern from "C_File_B.h": cdef struct C_Obj_B: pass cdef class pC_Obj_A: cdef const C_Obj_A * _c_self cdef class pC_Obj_B: cdef const C_Obj_B * _c_self cdef class pC_Obj_C: cdef const C_Obj_A * _c_a cdef const C_Obj_B * _c_b cdef class Obj_A_Wrap(pC_Obj_A): def __init__(self, pC_Obj_C obj_c): self._c_self = obj_c._c_a cdef class Obj_B_Wrap(pC_Obj_B): def __init__(self, pC_Obj_C obj_c): self._c_self = obj_c._c_b cdef class Stack: cdef public pC_Obj_A obj_a cdef public pC_Obj_B obj_b def __init__(self, pC_Obj_C obj_c): # Working self.obj_a = Obj_A_Wrap(obj_c) self.obj_b = Obj_B_Wrap(obj_c) # Working self.obj_a._c_self = obj_c._c_a self.obj_b = Obj_B_Wrap(obj_c) # Working self.obj_a = Obj_A_Wrap(obj_c) self.obj_b._c_self = obj_c._c_b # Not working self.obj_a._c_self = obj_c._c_a self.obj_b._c_self = obj_c._c_b 

I need a python object Stack with attrubutes accessible from Python, so I have added to Stack class cdef public pC_Obj_A obj_a and cdef public pC_Obj_B obj_b.These objects are wrappers to the C struct pointers.

When I initialize these objects with intermediary wrappers i.e. Obj_A_Wrap everything is fine.

When I initialize one of these objects directly i.e. self.obj_a._c_self = obj_c._c_a also everything is fine.

When both obj_a and obj_b are initialized directly (# Not Working part of code) I have got strange behaviour of my C library that inlcude C_File_A and C_File_B and respectively the C structs definitions. The behaviour is similar to memory corruption, or overwriting some parts of the memory that should not be.

I have no idea why the direct initialization causes this strange behaviour. Maybe you know?

1
  • 1
    Try adding the line print(self.obj_a, self.obj_b) at the start of __init__ - it might give you a clue what's going wrong. And bear in mind that some of what you label as "working" may just be "not crashing in an obvious way". Commented Nov 16, 2019 at 12:11

1 Answer 1

1

I have found the solution of my problem. When I was trying to solve this problem I have printed only _c_self attribute of the given object to check that the pointer was properly assigned and it was but when I printed entire object it turned out that python object is None instead of proper object declared as attribute.

print(self.obj_a, self.obj_b) # 66f000c0 66f000c0 print(f'{<int>self.obj_a._c_self:x} {<int>self.obj_b._c_self:x}') # None None 

The solution is to add Create function to cdef class:

cdef class pC_Obj_A: cdef const C_Obj_A * _c_self @staticmethod cdef Create(C_Obj_A * ptr): cdef pC_Obj_A result = pC_Obj_A() result._c_self = ptr return result 

And use it like this:

cdef class Stack: cdef public pC_Obj_A obj_a cdef public pC_Obj_B obj_b def __init__(self, pC_Obj_C obj_c): self.obj_a = pC_Obj_A.Create(obj_c._c_a) self.obj_b = pC_Obj_B.Create(obj_c._c_b) 

Then printout is:

print(self.obj_a, self.obj_b) # <pC_Obj_A object at 0x029FF610> <pC_Obj_B object at 0x029FF620> print(f'{<int>self.obj_a._c_self:x} {<int>self.obj_b._c_self:x}') # 2134b9c 2134c08 

And everything works great!

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.