On Thu, May 22, 2014 at 8:42 AM, Mateusz Czapliński <
czap...@gmail.com> wrote:
>
> So from this, am I correct to understand, that as long as I keep my
> unsafe.Pointer referenced (non-collectable), I can happily convert it to an
> uintptr and play with the uintptr value as much as I'd like (e.g., pass it
> to some .c)? I still have some concerns about this usecase, after reading a
> thread I've just found on golang-dev
> (
https://groups.google.com/d/msg/golang-dev/rd8XgvAmtAA/cI_hXa_FThcJ, which
> I don't fully understand, unfortunately), related to stacks copying -
> does/will this feature introduce additional issues for me here?
Yes, stack copying can be an issue in unusual cases. If you write
var a [5]int
p = unsafe.Pointer(&a[0])
v := uintptr(p)
f()
p = unsafe.Pointer(v)
then it is possible that the stack will have been copied during the
call to f, which could in some cases mean that p will no longer be
pointing at a.
As long as you retain a pointer in Go, it should be fine to convert a
Go pointer to uintptr and pass it to C. It doesn't matter what C does
with the value. That said, if you have a pointer value, it would in
general be better to pass an unsafe.Pointer to C rather than a
uintptr.
> Related to the pattern above: in goluago I link with Lua C code compiled by
> Go's cc; the Lua API sometimes takes a "void* userdata", which I used to
> convert back to some pointer in Go; so, this would still compile in 1.3, but
> be somehow "illegal"? Under assumption that the premise from my previous
> section is true, should I rather keep my unsafe.Pointers in some side
> storage as long as needed (to make uintptrs non-collectable), and also keep
> a map[uintptr]unsafe.Pointer, so that I could workaround the "illegal" part
> and, based on uintptr, only retrieve the unsafe.Pointer "legally" from the
> map? Or, am I OK to work "illegally" here by converting the uintptr received
> from C back to an unsafe.Pointer (as long as I keep an additional bookmarked
> reference to the unsafe.Pointer)? Or, none of above applies?
I don't think we've resolved the rules as to what should happen if you
have a pointer in Go, pass it to C, and then receive the pointer back
from C. In 1.3 that will work fine assuming the pointer is always
live in Go. However, in the future Go may have a moving garbage
collector. That would break this kind of code if the Go pointer
moves, since the value coming back from C would not have been
adjusted. When and if that happens, we will have to figure out the
rules that will ensure that the pointer passed to C does not move.
Using a map[uintptr]unsafe.Pointer is an interesting idea that might
actually work. But you don't need that for 1.3, although you do of
course need to keep the unsafe.Pointer alive somewhere on the Go side,
and such a map would be one way to do it.
> As to WinAPI, yes, I think I mean the case of pointers allocated by Windows.
> In such case, I feel unsure whether I can convert a uintptr, via
> unsafe.Pointer, to e.g. *byte, and use this to write a "func peek(base, off
> uintptr) byte { return *((*byte)(unsafe.Pointer(base+off))) }", or not?
That's fine. The change in Go 1.3 concerns value stored in memory,
and there is no such value here.
> Ah, and one more thing: in
https://github.com/akavel/rsrc, I create a .syso
> file with some data, and then create a Slice in C for accessing it, and
> return it through C->Go barrier as a []byte; is this unsafe, too, because it
> can make GC try to free that? Now that I think, it may be already unsafe
> this way even in Go 1.2. (Hm, maybe I should take a []byte argument and fill
> it? dunno, will have to think more about it probably.)
That's fine. The GC doesn't care about valid pointers that happen to
point into memory allocated by C. It won't try to do anything with
such a pointer.
Ian