英文:
Is C.GoBytes required to retrieve a C buffer, or is a pointer sufficient here?
问题
下面的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)
}
英文:
The cgo code below has a function to put a Go value in a C buffer, and two alternative functions to get it back; getViaGoBytes and getDirect.
Is getViaGoBytes any better than getDirect?
I assume not, and the intermediary slice created in getViaGoBytes is unnecessary.
Am I correct in thinking Go allocates enough memory when the uint64 y variable is declared, and the assignment to y copies the memory from C to 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
得分: 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
英文:
Marking question answered by copying JimB's answer from comment:
> 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.
Also, benchmark is interesting:
$ 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论