C.GoBytes 是否需要检索 C 缓冲区,或者这里的指针是否足够?

Is C.GoBytes required to retrieve a C buffer, or is a pointer sufficient here?

下面的 cgo 代码有一个将 Go 值放入 C 缓冲区的函数,以及两个取回它的替代函数; getViaGoBytes 和 getDirect。

getViaGoBytes 比 getDirect 好吗?

我假设不是,在 getViaGoBytes 中创建的中间切片是不必要的。

我认为 Go 在声明 uint64 y 变量时分配了足够的内存并且对 y 的赋值将内存从 C 复制到 Go 是否正确?

package main
/*
char buf[8];

void put(char * input, int size) {
    while (size--) {
        buf[size] = input[size];
    }
}
*/
import "C"
import "unsafe"

func put(input uint64) {
    C.put((*C.char)(unsafe.Pointer(&input)), C.int(unsafe.Sizeof(input)))
}

func getViaGoBytes() uint64 {
    var out uint64
    data := C.GoBytes(unsafe.Pointer(&(C.buf[0])), C.int(unsafe.Sizeof(out)))
    out = *(*uint64)(unsafe.Pointer(&data[0]))
    return out
}

func getDirect() uint64 {
    return *(*uint64)(unsafe.Pointer(&(C.buf[0])))
}

func main() {
    var input uint64 = 1<<64 - 1
    println(input)
    put(input)
    var x uint64 = getViaGoBytes()
    println(x)
    var y uint64 = getDirect()
    println(y)
}

通过从评论中复制 JimB 的答案来标记已回答的问题:

GoBytes copies a C allocated buffer into a slice with Go allocated memory. If that's what you want, then use GoBytes. Here you're not even keeping that copy, so there's no reason to do it.

此外,基准测试很有趣:

$ go test -bench . -benchmem
BenchmarkGoBytes-8      20000000            97.8 ns/op        32 B/op          3 allocs/op
BenchmarkDirect-8       2000000000           0.84 ns/op        0 B/op          0 allocs/op
PASS