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.

Reply via email to