From: Hraban Luyat Date: Mon, 22 Aug 2016 14:11:13 +0000 (+0100) Subject: Move callbacks struct to C allocator, to be safe X-Git-Tag: v2.0.0~70 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=223a3b298ca7b9dbf0b06ab6c50c66320f9dfa60;p=go-opus.git Move callbacks struct to C allocator, to be safe I'm not sure if the Go pointer proposal has already been implemented, but under the proposed restrictions allocating the callback struct in Go and passing that pointer to a C function which keeps it after returning is not allowed. This patch allocates the struct in C and passes the pointer from Go to C, which is fine. --- diff --git a/callbacks.c b/callbacks.c new file mode 100644 index 0000000..9148557 --- /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 b087c33..bc1b8a6 100644 --- a/stream.go +++ b/stream.go @@ -15,8 +15,7 @@ import ( #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 @@ func go_readcallback(p unsafe.Pointer, cbuf *C.uchar, cmaxbytes C.int) C.int { 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 @@ func (s *Stream) Init(read io.Reader) error { 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)