Given the *special cases* there https://pkg.go.dev/cmd/cgo#hdr-Special_cases, I would say this is not a good idea.
On Friday, November 25, 2022 at 9:06:05 AM UTC+1 Frédéric De Jaeger wrote: > Thanks for your reply. I was really missing an essential piece. > I found a bit weird that you need to write a helper to pass a uintptr to a > void* C function. It could be nice to allow that > > func Foo(x uintptr) { > C.foo((*C.char)x) > } > > but unfortunately, the compiler does not seem to accept it. Is there a > reason ? > > Anyway, I suppose the issue is that the runtime will interpret the > uintptr, when cast to a unsafe.Pointer as a potential valid pointer and if > it looks a bit too much like a legit go pointer, that might confuse the > GC. I suppose that unsafe.Pointer can safely handle C pointers (from the > doc of cgo) > > If the uintptr contains a valid C pointer, do we have a practical issue, > like with the following code ? > > func main() { > v := uintptr(unsafe.Pointer(C.CString("Hello from stdio"))) > C.myprint(unsafe.Pointer(v)) > C.free(unsafe.Pointer(cs)) > } > > This is a question about the current implementation, I know it violates > the rule of unsafe.Pointer. This is just to have a better understanding > about what the runtime does and when (at conversion time? C call time ? GC > time ?) > > > From your last paragraph, can I do that ? > > /* > #include <stdint.h> > static void* IntToPtr(uintptr_t v) { return (void*)v; } > */ > import "C" > > import ( > "runtime/cgo" > "unsafe" > ) > > func HandleAsPointer(h cgo.Handle) unsafe.Pointer { > return C.IntToPtr(C.uintptr_t(uintptr(h))) > } > > Here the cast int -> void* happens in the C world and the conversion back > to unsafe.Pointer looks legit according to the rule of cgo. But this will > create an unsafe.Pointer containing a totally invalid pointer. Will it > work (practically and theoretically) ? Is the GC robust against the > presence of a random value in an unsafe.Pointer ? > > Thanks > > > On Wednesday, November 23, 2022 at 9:31:45 PM UTC+1 Ian Lance Taylor wrote: > >> On Wed, Nov 23, 2022 at 9:25 AM Frédéric De Jaeger >> <fdej...@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/b42d57a0-c1bd-43ad-8679-4a376b211e81n%40googlegroups.com.