indoorvivants / sn-bindgen

Scala 3 native binding generator + libclang facade
https://sn-bindgen.indoorvivants.com
80 stars 8 forks source link

scala.MatchError: CType.Reference(name = Unnamed) (of class bindgen.CType$Reference) #153

Closed faveoled closed 1 year ago

faveoled commented 1 year ago

I'm getting the error below when trying to generate bindings for libnotify. Don't know if it's a bug and can't determine the cause easily.

^^ omitted for brevity
[bindgen] info Struct 'GNativeSocketAddressClass' was detected as having cycles
[bindgen] info Struct 'GNetworkAddressClass' was detected as having cycles
[bindgen] info Struct 'GNetworkServiceClass' was detected as having cycles
[bindgen] info Struct 'GNode' was detected as having cycles
[bindgen] info Struct 'GObjectClass' was detected as having cycles
[bindgen] info Struct 'GOutputStreamClass' was detected as having cycles
scala.MatchError: CType.Reference(name = Unnamed) (of class bindgen.CType$Reference)
        at java.lang.Throwable.fillInStackTrace(Unknown Source)
        at bindgen.rendering.sizes_and_alignments$package$.alignment(Unknown Source)
        at scala.collection.immutable.List.map(Unknown Source)
        at bindgen.rendering.sizes_and_alignments$package$.alignment(Unknown Source)
        at bindgen.rendering.sizes_and_alignments$package$.accumulate$1(Unknown Source)
        at scala.collection.immutable.List.map(Unknown Source)
        at bindgen.rendering.struct$package$.struct(Unknown Source)
        at bindgen.rendering.binding$package$$$Lambda$30.applyVoid(Unknown Source)
        at scala.runtime.function.JProcedure2.apply(Unknown Source)
        at bindgen.rendering.binding$package$.renderAll$1$$anonfun$1(Unknown Source)
        at bindgen.rendering.binding$package$$$Lambda$21.applyVoid(Unknown Source)
        at scala.runtime.function.JProcedure1.apply(Unknown Source)
        at scala.collection.immutable.List.foreach(Unknown Source)
        at bindgen.rendering.binding$package$.binding$$anonfun$2(Unknown Source)
        at bindgen.rendering.binding$package$$$Lambda$4.applyVoid(Unknown Source)
        at scala.runtime.function.JProcedure1.apply(Unknown Source)
        at bindgen.rendering.binding$package$.binding(Unknown Source)
        at bindgen.Generate$.main$$anonfun$1(Unknown Source)
        at bindgen.Generate$$$Lambda$1.applyVoid(Unknown Source)
        at scala.runtime.function.JProcedure1.apply(Unknown Source)
        at scala.scalanative.unsafe.Zone$.apply(Unknown Source)
        at <none>.main(Unknown Source)
        at <none>.(Unknown Source)
        at <none>.__libc_start_main(Unknown Source)
        at <none>._start(Unknown Source)
keynmol commented 1 year ago

Hi @faveoled!

First of all, could you try with the latest version? sbt devPublish will publish bindgen locally, and output the version to use in plugins.sbt.

I'm not confident it will solve it, but worth a try.

Apart from that - I could use your help reproducing it.

I have a Linux machine (ubuntu-based), but I need to know:

  1. How you installed libnotify
  2. How you configured the binding (i.e. where are the files you pointed at)

If I can reproduce I can attempt to solve it - my own attempts at building GTK (and surrounding) bindings have been abysmal because of similar issues, and I'd love to figure out common cause.

faveoled commented 1 year ago
sudo apt install libgdk-pixbuf-2.0-dev libglib2.0-dev libnotify-dev
user@hp-laptop:~$ dpkg -S /usr/include/libnotify/notification.h 
libnotify-dev:amd64: /usr/include/libnotify/notification.h
bindgenBindings := Seq(
  Binding(
  /* 1 */  (new File("/usr")) / "include" / "libnotify" / "notification.h",
  /* 2 */  "libnotify",
  /* 3 */  cImports = List("glib.h", "string.h", "simple.h"),
           clangFlags = List(
             "-I/usr/include/glib-2.0",
             "-I/usr/lib/x86_64-linux-gnu/glib-2.0/include/",
             "-I/usr/include/gdk-pixbuf-2.0",
           )
  )
)

Maybe I'll try devPublish if I have time

keynmol commented 1 year ago

Reproduced on HEAD and also found the root cause, but the fix doesn't seem to be trivial.

The minimisation:

typedef struct {
  // looks similar but is rendered correctly
  union {
    long test;
    char* help;
  } yo;

  // cause of the issue
  union {
    long test;
    char* help;
  } data[2];
} StructWithUnionArray;

the yo field will render successfully, the data[2] will not.

The issue is that the AST at this particular location in the source file doesn't define the anonymous union first and then define the field - instead all you get is a ConstantArray type and nothing else.

faveoled commented 1 year ago

Clear, thanks

keynmol commented 1 year ago

Well actually, I fixed it in minutes :D Just going to run a few examples and open a PR

keynmol commented 1 year ago

I linked a PR that fixes this particular issue and the one you reported before (thanks for those!) PR also contains a fully rendered libnotify binding - but it still won't compile

Unfortunately, we're now hitting a crash in the compiler itself, which I've known about before. It's present in this particular situation because libnotify brings in transitively lots of types from glib (which is gigantic) and the binding i just huge.

Once that PR is merged I will close this particular issue, and open a new one to figure out how to avoid crashing the compiler

faveoled commented 1 year ago

Ok. I guess my IDE will crash as well on such big files