Пишу, по большей части, про историю, свою жизнь и немного про программирование.

Структуры и CGO

Обновление: в комментариях в Фейсбуке мне бывший коллега попенял, что я забыл Си и что поведение правильное — тут объявляется анонимная структура, а потом к ней определяется тип. Верно, практики на Си у меня за последние годы почти не было, вымылось всё из памяти. Так что текст ниже читайте с учётом этого обновления заметки.

Каждый раз расстраиваюсь, когда сталкиваюсь с CGO. Идея-то прекрасная — встраивать в программы на Гоу сишные библиотеки почти без программирования на Си. Но частности всё убивают. То нельзя функцию по указателю передать, то вот убил час с утра сегодня, пытаясь починить ошибку в своей библиотеке go-gd.

Документация говорит нам, что сишные структуры доступны в Гоу через конструкцию C.struct_name, а её размер — через C.sizeof_struct_name.

Я так и пытался сделать и получал ошибки:

package main

/*
typedef struct {
    int x, y;
} test;
*/
import "C"
import . "fmt"

func main() {
    Println(C.struct_test{}) // «{}»? Что за…
    Println(C.sizeof_struct_test) // could not determine kind of name for C.sizeof_struct_test
}

Упрощённый код выше кратко иллюстрирует проблему. В первом случае никакая ошибка не выводится (что ещё больше сбивает с толку), но структура почему-то пустая. Во втором случае компилятор выдаёт ошибку, но от этого не легче — при конфликте моих знаний с документацией как правило думаю, что права документация, потому около часа пытался понять где я тут умудрился накосячить.

Оказывается, и я набрёл на это случайно, в ходе экспериментов, struct просто не надо писать, тогда всё будет работать:

Println(C.test{}) // «{0 0}»
Println(C.sizeof_test) // 8

Если будет время, ещё поизучаю этот вопрос — посмотрю историю коммитов и всё такое, возможно была какая-то движуха, которую не отразили в документации, либо просто что-то сломали. Надеюсь кому-нибудь сэкономлю время этой заметкой.