callbacks.c | 17 +++++++++++++++++ stream.go | 12 ++---------- diff --git a/callbacks.c b/callbacks.c new file mode 100644 index 0000000000000000000000000000000000000000..9148557712ae804fefa8aa0c924bce634148c3f7 --- /dev/null +++ b/callbacks.c @@ -0,0 +1,17 @@ +// Copyright © 2015, 2016 Hraban Luyat +// +// License for use of this code is detailed in the LICENSE file + +// Allocate callback struct in C to ensure it's not managed by the Go GC. This +// plays nice with the CGo rules and avoids any confusion. + +#include + +// Defined in Go. Uses the same signature as Go, no need for proxy function. +int go_readcallback(void *p, unsigned char *buf, int nbytes); + +// Allocated once, never moved. Pointer to this is safe for passing around +// between Go and C. +struct OpusFileCallbacks callbacks = { + .read = go_readcallback, +}; diff --git a/stream.go b/stream.go index b087c33d33083faf7c6c1e40ea5ef57b4c804b3d..bc1b8a6ddc99f0a21b5904e978d9687b38eb576a 100644 --- a/stream.go +++ b/stream.go @@ -15,8 +15,7 @@ #cgo pkg-config: opus #include #include -// Uses the same signature as Go, no need for proxy -int go_readcallback(void *p, unsigned char *buf, int nbytes); +extern struct OpusFileCallbacks callbacks; */ import "C" @@ -61,13 +60,6 @@ C.memcpy(unsafe.Pointer(cbuf), unsafe.Pointer(&stream.buf[0]), C.size_t(n)) return C.int(n) } -var callbacks = C.struct_OpusFileCallbacks{ - read: C.op_read_func(C.go_readcallback), - seek: nil, - tell: nil, - close: nil, -} - func NewStream(read io.Reader) (*Stream, error) { var s Stream err := s.Init(read) @@ -104,7 +96,7 @@ defer streams.Del(s) oggfile := C.op_open_callbacks( // "C code may not keep a copy of a Go pointer after the call returns." unsafe.Pointer(s.id), - &callbacks, + &C.callbacks, nil, 0, &errno)