在这里,需要使用C.GoBytes来检索C缓冲区,还是只需要一个指针就足够了?

huangapple go评论75阅读模式
英文:

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 &quot;C&quot;
import &quot;unsafe&quot;

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

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

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

func main() {
	var input uint64 = 1&lt;&lt;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

huangapple
  • 本文由 发表于 2016年11月21日 04:19:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/40708924.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定