Search code examples
rakurakudonativecall

Using void structs in Raku via NativeCall


I'm trying to link libzip to Raku, and it uses a void struct or a struct with no body, like this:

struct zip;
typedef struct zip zip_t;

I declare it in my Raku program in the same way:

class zip_t is repr('CStruct'){};

This fails with:

Class zip_t has no attributes, which is illegal with the CStruct representation.

Only reference I have found to that error is in this non-addressed issue in MyHTML. That might make it a regression, but I'm really not sure. Any idea?


Solution

  • A google for "no attributes, which is illegal with the CStruct representation" yields three matches. The third leads to the following recent bug/change for module LibZip:

    - class zip is repr('CStruct') is export { }
    + class zip is repr('CPointer') is export { }
    

    Before I publish this I see Curt Tilmes has commented to similar effect.


    I know little about C. But I enjoy researching things. This answer is a guess and some notes based on googling.

    • The error message you've quoted is about NativeCall, which in turn means it's about the Rakudo compiler, not the Raku language. (I presume you know this, and for many folk and situations the distinction isn't typically important, but I think it worth noting in this case.)

    • The top SO match for a google for "empty struct" is Empty structs in C. The question asks about the semantics of empty structs and using them with a foreign language. The question and its answers seem useful; the next few points are based on excerpts from them.

    • "Structures with no named members [have undefined behavior]". I'd say this explains why you're getting the NativeCall error message ("no attributes, which is illegal with the CStruct representation".). NativeCall is about having a reliable portable interface to C so it presumably must summarily reject undefined aspects. (Perhaps the error message could hint at what to do instead? Probably not. It's probably better that someone must search for matches to the message, just as you have done. And then presumably they would see this SO.)

    • I presume you're just trying to bind with libzip's empty struct as part of passing data back and forth without reading or writing it. I suspect that that is the crux of the problem here; how do you bind given that NativeCall (quite reasonably) refuses to do it in the usual manner?

    • "From the point of view of writing [a foreign language] binding to a C library ... You're never going to do anything with objects of the [empty struct] type except pass them to imported C functions." I presume this is true for your situation and that anything else would be undefined behavior per the C spec and thus at least tied to a specific C compiler for both the C library and the C compiler used to compile Rakudo and quite possibly undefined even then. I presume Curt has asked about your usage in case the binding is doing or requiring something crazy, but I very much doubt that it is.