需要使用C.GoBytes来检索C缓冲区吗?还是仅需要一个指针就足够了?

3
下面的cgo代码有一个将Go值放入C缓冲区的函数,以及两个获取它的替代函数;getViaGoBytes和getDirect。
getViaGoBytes比getDirect更好吗?
我认为不是,而在getViaGoBytes中创建的中介切片是不必要的。
我是否正确地认为当声明uint64 y变量并将其赋值时,Go会分配足够的内存,并且将内存从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)
}

1
即使您只将1向左移动63位,在C中,当int为32位时,uint64_t n = 1<<63;将无法工作,需要使用uint64_t n = (uint64_t)1<<63;。其次,向左移动64位将使您最终得到0。这是否适用于Go语言,特别是第二点? - Weather Vane
谢谢@WeatherVane,我不知道在C中需要强制转换!在Go中,根据运算符优先级,1<<64 - 1是(1<<64) - 1。由gofmt强制的布局试图暗示优先级。关于第二点,在Go中常量可以非常大,只要它们适合赋值类型即可。例如1 << 400。还请参阅常量表达式。当上述代码运行时,它会写入18446744073709551615三次。 - Mark
1
GoBytes将一个由C分配的缓冲区复制到使用Go分配的内存的切片中。如果这正是你想要的,那就使用GoBytes。在这里,你甚至没有保留那个副本,所以没有理由这样做。 - JimB
谢谢@JimB,你回答了我的问题,非常感谢 :-) - Mark
1个回答

2

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

GoBytes将C分配的缓冲区复制到具有Go分配的内存的切片中。 如果这是您想要的,请使用GoBytes。 在这里,您甚至没有保留该副本,因此没有理由这样做。

此外,基准测试很有趣:

$ 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接