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.

Reply via email to