Skip to content
Go back

CGO Rabbit Hole

Table of contents

Open Table of contents

Problem

Libvips is written in C++. It’s an image processing library designed for low memory consumption. But I wanted to use go to manipulate the library. To do this, you needed to use vipsgen. A library that uses CGO Introspection to analyze the libvips API and code generate the corresponding go library.

Initial Encounter

On January 7, 2026, the vipsgen go package was updated to 1.3.1. This version mapped correctly to the libvips version 1.18.5. The prior version 1.3.0 did not. So I ended up in a bad situation where the pregenerated code package does not run and the header file vips.h is missing types such as ‘VipsForeignPdfPageBox’. When I self generated the code bindings, they would work. So now, I’m digging in the hole to figure out where the broken dependency is and why.

Second Encounter

Naturally, the next step is to compare the diff of the two files. The one that I generated and the one that go is complaining about. First observation is that the failing file is for libvips 8.18.0 and my self generated file is for 8.15.

libvips-dev/noble,now 8.15.1-1.1build4 amd64 [installed]

This line shows I have version 8.15.1 installed and thus only the bindings for that version are usable and the latest version bindings (8.18.0) are not compatible.

Continued Doubts

In file included from /home/.../go/pkg/mod/github.com/cshum/[email protected]/vips/image.go:5:
./vips.h:591:178: error: unknown type name 'VipsForeignPdfPageBox'; did you mean 'VipsForeignFlags'?

When you diff the two files, vips.h, you can see that the accpetable one does not contain the problematic types.

CGO Workings

CGO works by looking at the C preamble and any #include directives. It then generates C code that addresses the “calling conventions” between Go and C.

Structure

┌─────────────────────────────────────────────────────────────┐
│                    Go Method Layer                          │
│  • Methods on *Image struct                                 │
│  • Go enums and structs                                     │
│  • Options structs for optional parameters                  │
│  • Type conversions (Go <-> C)                              │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│                   Go Binding Layer                          │
│  • vipsgenAbc() - required parameters only                  │
│  • vipsgenAbcWithOptions() - with optional parameters       │
│  • C array handling and memory management                   │
│  • String conversions and cleanup                           │
│  • Error handling and resource management                   │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│                     C Layer                                 │
│  • vipsgen_abc() - required args only                       │
│  • vipsgen_abc_with_options() - all parameters              │
│  • VipsOperation dynamic dispatch                           │
│  • Proper VipsArray creation and cleanup                    │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│                    libvips                                  │
│  • vips_abc() - original variadic functions                 │
│  • VipsOperation object system                              │
│  • GObject introspection metadata                           │
└─────────────────────────────────────────────────────────────┘

Share this post on:

Previous Post
Go Zero Values
Next Post
AWS Structure