cgo: passing unsafe.Pointer of Slice without explicit pinning?

56 views
Skip to first unread message

Antonio Caceres Cabrera

unread,
Jul 7, 2024, 9:17:28 AM (15 hours ago) Jul 7
to golang-nuts
Hi Gophers,

I'm trying to use cgo for a C library, specifically a function which takes a void pointer to a buffer, and I'm trying to pass a Go-Slice as this buffer.

```
func Write(buf []byte) (int, error) {
    // var pin rumtime.Pinner
    // pin.Pin(&buf[0])
    // defer pin.Unpin()
    // is this necessary? Is it even safe?
    ...
    ret := C.lib_read(unsafe.Pointer(&buf[0]), C.int(len(buf))) // function which reads from this buffer
    ...
}
```
Does this require explicit pinning of buf? And if so, is the commented part a valid pinning of a slice? The documentation states that pointers passed to C functions are implicitly pinned (on the top-level that is), but does this also apply to slices, i.e. if I pass a (unsafe) pointer to the first element, is the slice's entire backing array implicitly pinned?

I know that there are some runtime checks for this, but I am worried that any use of unsafe.Pointer might perhaps override these checks completely.

Thanks a lot.

Julio

Ian Lance Taylor

unread,
Jul 7, 2024, 11:38:13 AM (13 hours ago) Jul 7
to Antonio Caceres Cabrera, golang-nuts
This kind of code does not require explicit pinning. As you note,
passing a pointer to C implicitly pins the memory that the pointer
points to. Further, the cgo docs say "When passing a pointer to an
element in an array or slice, the Go memory in question is the entire
array or the entire backing array of the slice." In other words, yes,
the slice's entire backing array is implicitly pinned. The cgo tool
is smart enough to ignore type conversions when deciding what memory
needs to be pinned.

Ian
Reply all
Reply to author
Forward
0 new messages