14

In Cython glue declarations, how do I represent a C struct type containing an anonymous union? For example, if I have a C header file mystruct.h containing

struct mystruct
{
    union {
        double da;
        uint64_t ia;
    };
};

then, in the corresponding .pyd file

cdef extern from "mystruct.h":
    struct mystruct:
        # what goes here???

I tried this:

cdef extern from "mystruct.h":
    struct mystruct:
        union {double da; uint64_t ia;};

but that only gave me "Syntax error in C variable declaration" on the union line.

zwol
  • 135,547
  • 38
  • 252
  • 361
polerto
  • 1,750
  • 5
  • 29
  • 50
  • 7
    I don't understand why this question was closed. It appears reasonably helpful to other Cython users, it has a good title and tags, and finally an accepted answer. How is it "too localized"? – user4815162342 Nov 03 '12 at 09:00
  • Yeah, the expression of this question made it sound highly specialized, but it's actually a generic problem that anyone trying to glue a complicated C library into a Python extension might face. I've tried to make it clearer that the code in the question is just an example of a generic scenario. – zwol Nov 08 '14 at 01:43

2 Answers2

16

For those who got here via Google, I found a solution to this. If you have a struct:

typedef struct {
    union {
        int a;
        struct {
            int b;
            int c;
        };
    }
} outer;

You can flatten it all out in the Cython declaration, like so:

ctypedef struct outer:
    int a
    int b
    int c

Cython isn't generating any code that makes any suppositions about the memory layout of your struct; you're only telling it the de facto structure of what you're calling by telling it what syntax to generate to call it. So if your structure has a member of size int that can be accessed as ((outer) x).a, then you can throw a on the struct definition and it will work. It's operating on textual substitution, not memory layout, so it doesn't care about whether these things are in anonymous unions or structs or what have you.

Haldean Brown
  • 12,411
  • 5
  • 43
  • 58
  • Trying something similar in my code caused a compilation error, saying outer has no member named 'b'. – Noich Dec 18 '17 at 11:04
  • @Noich: got a pastebin or something with your Cython and C code? I can take a look. – Haldean Brown Dec 18 '17 at 20:12
  • The C code is here https://pastebin.com/psTBpJut Trying a named struct: https://pastebin.com/jH7Rqsu1 Trying to flatten: https://pastebin.com/T8GGgKtA Thanks! – Noich Dec 19 '17 at 13:42
  • 1
    @Noich this question is about anonymous structs or unions; your struct is named, therefore not anonymous, so you have to create a special struct definition for the nested one. – Haldean Brown Dec 22 '17 at 02:11
  • I tried the 2 options I saw mentioned in similar contexts, both fail. Do you have a different suggestion? – Noich Dec 24 '17 at 09:18
  • @Noich: that's a separate question; I'd recommend asking a new question and sticking a link here. Comment boxes are a bad way to answer questions! Thanks. – Haldean Brown Jan 03 '18 at 00:35
10

You can't nest declarations to the best of my knowledge, and Cython doesn't support anonymous unions AFAIK.

Try the following:

cdef union mystruct_union:
    double lower_d
    uint64_t lower

cdef struct mystruct:
    mystruct_union un

Now access the union members as un.lower_d and un.lower.

nneonneo
  • 171,345
  • 36
  • 312
  • 383