On Wed, Nov 23, 2022 at 9:25 AM Frédéric De Jaeger <fdejae...@novaquark.com> wrote: > > There is something that puzzles me a lot in the doc about cgo.Handle there > https://pkg.go.dev/runtime/cgo. It says: > > Some C functions accept a void* argument that points to an arbitrary data > value supplied by the caller. It is not safe to coerce a cgo.Handle (an > integer) to a Go unsafe.Pointer, but instead we can pass the address of the > cgo.Handle to the void* parameter, as in this variant of the previous example: > > I was under the impression that casting a uintptr to an unsafe.Pointer just > to call a C function (that accepts a void*) is somewhat valid. (This is not > clearly specified as a valid case in the doc of unsafe.Pointer, so, it might > be invalid from a very pedantic point of view). > > The advice given in the doc looks worst. Taking the address of a local > variable and giving it to C looks even more undefined (if C stores the > pointer and reuse it after the original call returns). > > Don't we have a doc issue there ? > > I know that in C, the conversion uintptr -> void* is subject to debate (trap > representation, ...). In practice, nobody cares because It just works. > (example of the nobody cares > https://www.freedesktop.org/software/gstreamer-sdk/data/docs/latest/glib/glib-Type-Conversion-Macros.html) > > In practice, I'm almost certain that the naïve code that just gives the > cgo.Handle to a C function as a void* is *much* safer that the pattern > suggested in the doc. > > So should the doc be changed, or am I missing some important piece ?
It is not safe to convert a uintptr to an unsafe.Pointer when calling a C function. The docs in the unsafe package are intended to be precise, and in particular the compiler is aware of them. The compiler applies special handling to a conversion from unsafe.Pointer to uintptr in the argument to a function with no body like syscall.Syscall. That special handling does not occur in calls to cgo functions. While it will often work in practice, there are cases where it will fail. One way to handle this kind of case is to write a tiny C wrapper in the cgo comment that takes a uintptr and does the conversion to void* in C. That conversion is safe, because the Go runtime will not be aware of it and will never mistakenly treat the uintptr value as a pointer value. Ian -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAOyqgcWbB0k1pffy2j7GA0fOj3mGQ%3DG9M0CKc_%2BRhoLLJ9iJDg%40mail.gmail.com.