programmatically get address of struct fields and/or cdef attrs

21 views
Skip to first unread message

Peter Schay

unread,
May 17, 2025, 1:19:49 PMMay 17
to cython...@googlegroups.com
Hi,
I have thought of two imperfect ways to solve this and I wonder if there is anything easier.

cdef struct Bar:
    int a, b, c

cdef class Foo:
    cdef public Bar bar

    def get_addr_of_bar_attr(self, name='a'):
        # Instead of the NULL placeholder here,
        # is there a way to get address of self.bar.<name>?
        cdef void *p = NULL
        print(f'address of {name} is {<long long>p}')

I looked at the generated __pyx_convert__to_py_struct__ code but it appears the loop was already done by Cython's compiler; i.e. the attributes are handled one by one.

The only ways I can think of:
1) Explicitly initialize a python dict mapping {'a' : <long long>&self.bar.a, ...}
2) Build the same dict dynamically at initialization in a somewhat questionable manner: get the cython dict for the struct and for each key: set the value to ~0, scan the memory to find the address of the change, reset to 0.

Thanks!
Peter

Prakhar Goel

unread,
May 17, 2025, 1:33:46 PMMay 17
to cython...@googlegroups.com

It would be nice if there was some way to get the C structure underlying a cdef class. Then we could use the usual offsetof and friends. There are a few (unusual) situations I've needed the same thing and had to hack around the problem.

-- PG


--

---
You received this message because you are subscribed to the Google Groups "cython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cython-users...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/cython-users/CALKyFjY2D7ipZNN0QLs15X4sKjw52_F5P6W-dQwyKCoE-d%2BkOw%40mail.gmail.com.

Peter Schay

unread,
May 18, 2025, 12:37:30 PMMay 18
to cython...@googlegroups.com
On Sat, May 17, 2025 at 1:33 PM Prakhar Goel <newt...@gmail.com> wrote:

It would be nice if there was some way to get the C structure underlying a cdef class. Then we could use the usual offsetof and friends. There are a few (unusual) situations I've needed the same thing and had to hack around the problem.

-- PG


Thanks; yes I suppose there is no official way.  Using memset and the Cython struct-to-dict feature and a few loops I was able to implement something simple that works with 64-bit and 32-bit int fields, which is all I need.
The C+Python frankenstein function, followed by sample output:

cdef object structfields(obj, void *sp, int ssize, str sname):
    ...

$ python
Python 3.13.3 (main, May 16 2025, 18:06:26) [Clang 17.0.0 (clang-1700.0.13.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from entries import Foo; f = Foo(); f.getaddrs()
StructField(name='x', nbits=64, offset=0, signed=False)
StructField(name='a', nbits=32, offset=8, signed=True)
StructField(name='b', nbits=32, offset=12, signed=True)
StructField(name='c', nbits=32, offset=16, signed=True)
StructField(name='u', nbits=32, offset=20, signed=False)
StructField(name='y', nbits=64, offset=24, signed=False)

Poor-man's Cython introspection! :-)


 
Reply all
Reply to author
Forward
0 new messages