Сбор мусора и cgo

Возможно ли сделать сборщик мусора в дескрипторе Go и освободить память, выделенную с помощью кода C? Прошу прощения, я не использовал C и cgo, чтобы мои примеры, возможно, нуждались в некоторых разъяснениях.

Предположим, у вас есть библиотека C, которую вы хотите использовать, и эта библиотека выделяет некоторую память, которую необходимо освободить вручную. Я хотел бы сделать что-то вроде этого:

package stuff

/*
#include <stuff.h>
*/
import "C"

type Stuff C.Stuff

func NewStuff() *Stuff {
    stuff := Stuff(C.NewStuff()) // Allocate memory

    // define the release function for the runtime to call
    // when this object has no references to it (to release memory)   
    // In this case it stuff.Free()     

    return stuff

}

func (s Stuff) Free() {
    C.Free(C.Stuff(s)) // Release memory
}

Есть ли способ, чтобы сборщик мусора вызывал Stuff.Free(), когда нет ссылок на * Stuff в run runtime?

Имею ли смысл здесь?

Возможно, более прямой вопрос: возможно ли, чтобы среда выполнения автоматически обрабатывала очистку выделенной памяти C, записывая функцию, которую выполняет среда выполнения, когда нулевые ссылки на этот объект?

Ответ 1

Существует функция runtime.SetFinalizer, но она не может использоваться ни на одном объекте, выделенном кодом C.

Однако вы можете создать объект Go для каждого объекта C, который должен быть освобожден автоматически:

type Stuff struct {
    cStuff *C.Stuff
}

func NewStuff() *Stuff {
    s := &Stuff{C.NewStuff()}
    runtime.SetFinalizer(s, (*Stuff).Free)
    return s
}

func (s *Stuff) Free() {
    C.Free(s.cStuff)
}