Created a Go Binding Generator for libvips #4538
Replies: 3 comments 9 replies
-
Hi @cshum, yes I saw your hackernews and bsky posts about this. Very nice! Did you read the libvips C++ binding? It's a little similar -- there's a not-typesafe Maybe even writing a non-typesafe implementation is impossible in Go? I've not used the language. Perhaps we've discussed this! I forget. I guess you've tested for reference leaks? If you run your test suite with Would you like a link to your project in the libvips README? |
Beta Was this translation helpful? Give feedback.
-
The libvips C++ API static generator script, in case you didn't see it: https://github.com/libvips/libvips/blob/master/cplusplus/gen-operators.py One other thing you could consider is an option to automatically download the correct libvips binary at install time (no idea if the Go package manager allows this). We have precompiled binaries for linux (glibc and musl), win and macos, each x64 and arm64, so you just detect the platform and grab the right one. It could potentially make vipsgen a lot easier to install. |
Beta Was this translation helpful? Give feedback.
-
The generator script, yes! I was taking inspiration from gen-operators.py plus a few others, including the introspection code in C++, Rust, etc. You're right about the similarity to the C++ binding approach. I did study the C++ implementation, and yes - Go's compile-time requirements make a non-typesafe Technically, one could potentially achieve a dynamic implementation by passing arguments as raw byte buffers and doing runtime type reflection/marshalling or something similar - but the performance overhead would be huge. CGO is already quite slow compared to native Go code. The rule of thumb of calling C from Go is to minimize the number of calls between C and Go, hence pre-generating the possible paths. I believe there were Go projects that tried the dynamic approach, found it too slow, and went back to the hand-written arguments approach. My first intention was actually to automate my hand-written bindings and to make sure the generated binding (e.g. tiffsave_buffer optional arguments looks like this) is no worse than my hand-written code. Since C is not my main language, writing the code by hand was not an easy job for me! The automatic binary download idea is fascinating! Though Go needs to compile against the libvips headers, not just link to the shared libraries, which adds complexity. Great point about reference leak testing - yes, a better test suite with leak checking would be at the top of my upcoming todo list. Reference management is tricky, and having automated validation would be invaluable. I'd be honored to have a link in the libvips README! 🙏 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Having worked with libvips in Go for a few years, writing manual CGO bindings is painful and error-prone.
Compared to Python, Ruby, or JavaScript, Go is a restrictive language where everything must be declared at compile time, and solutions like dynamic FFI are unlikely.
In the Go community, code generation has become the chosen approach for automating boilerplate while maintaining type safety: gqlgen for GraphQL, sqlboiler for database ORMs, and many others.
Despite the limitations of runtime GObject introspection, it's actually the most feasible path for Go - code generation using GObject introspection:
https://github.com/cshum/vipsgen
This leads me to my new project vipsgen - a Go binding generator for libvips using GObject introspection. The generator produces type-safe bindings that adapt to different libvips installations.
Beta Was this translation helpful? Give feedback.
All reactions