// plays nice with the CGo rules and avoids any confusion.
#include <opusfile.h>
+#include <stdint.h>
// Defined in Go. Uses the same signature as Go, no need for proxy function.
int go_readcallback(void *p, unsigned char *buf, int nbytes);
struct OpusFileCallbacks callbacks = {
.read = go_readcallback,
};
+
+// Proxy function for op_open_callbacks, because it takes a void * context but
+// we want to pass it non-pointer data, namely an arbitrary uintptr_t
+// value. This is legal C, but go test -race (-d=checkptr) complains anyway. So
+// we have this wrapper function to shush it.
+// https://groups.google.com/g/golang-nuts/c/995uZyRPKlU
+OggOpusFile *
+my_open_callbacks(uintptr_t p, const OpusFileCallbacks *cb, int *error)
+{
+ return op_open_callbacks((void *)p, cb, NULL, 0, error);
+}
/*
#cgo pkg-config: opusfile
#include <opusfile.h>
+#include <stdint.h>
#include <string.h>
extern struct OpusFileCallbacks callbacks;
+OggOpusFile *my_open_callbacks(uintptr_t p, const OpusFileCallbacks *cb, int *error);
*/
import "C"
// called.
streams.Save(s)
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),
- &C.callbacks,
- nil,
- 0,
- &errno)
+ oggfile := C.my_open_callbacks(C.uintptr_t(s.id), &C.callbacks, &errno)
if errno != 0 {
return StreamError(errno)
}