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

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

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中,对吗?

  1. package main
  2. /*
  3. char buf[8];
  4. void put(char * input, int size) {
  5. while (size--) {
  6. buf[size] = input[size];
  7. }
  8. }
  9. */
  10. import "C"
  11. import "unsafe"
  12. func put(input uint64) {
  13. C.put((*C.char)(unsafe.Pointer(&input)), C.int(unsafe.Sizeof(input)))
  14. }
  15. func getViaGoBytes() uint64 {
  16. var out uint64
  17. data := C.GoBytes(unsafe.Pointer(&(C.buf[0])), C.int(unsafe.Sizeof(out)))
  18. out = *(*uint64)(unsafe.Pointer(&data[0]))
  19. return out
  20. }
  21. func getDirect() uint64 {
  22. return *(*uint64)(unsafe.Pointer(&(C.buf[0])))
  23. }
  24. func main() {
  25. var input uint64 = 1<<64 - 1
  26. println(input)
  27. put(input)
  28. var x uint64 = getViaGoBytes()
  29. println(x)
  30. var y uint64 = getDirect()
  31. println(y)
  32. }
英文:

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?

  1. package main
  2. /*
  3. char buf[8];
  4. void put(char * input, int size) {
  5. while (size--) {
  6. buf[size] = input[size];
  7. }
  8. }
  9. */
  10. import &quot;C&quot;
  11. import &quot;unsafe&quot;
  12. func put(input uint64) {
  13. C.put((*C.char)(unsafe.Pointer(&amp;input)), C.int(unsafe.Sizeof(input)))
  14. }
  15. func getViaGoBytes() uint64 {
  16. var out uint64
  17. data := C.GoBytes(unsafe.Pointer(&amp;(C.buf[0])), C.int(unsafe.Sizeof(out)))
  18. out = *(*uint64)(unsafe.Pointer(&amp;data[0]))
  19. return out
  20. }
  21. func getDirect() uint64 {
  22. return *(*uint64)(unsafe.Pointer(&amp;(C.buf[0])))
  23. }
  24. func main() {
  25. var input uint64 = 1&lt;&lt;64 - 1
  26. println(input)
  27. put(input)
  28. var x uint64 = getViaGoBytes()
  29. println(x)
  30. var y uint64 = getDirect()
  31. println(y)
  32. }

答案1

得分: 2

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

GoBytes将C分配的缓冲区复制到使用Go分配的内存的切片中。如果这是你想要的,那就使用GoBytes。在这里,你甚至没有保留这个副本,所以没有理由这样做。

此外,基准测试也很有趣:

  1. $ go test -bench . -benchmem
  2. BenchmarkGoBytes-8 20000000 97.8 ns/op 32 B/op 3 allocs/op
  3. BenchmarkDirect-8 2000000000 0.84 ns/op 0 B/op 0 allocs/op
  4. 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:

  1. $ go test -bench . -benchmem
  2. BenchmarkGoBytes-8 20000000 97.8 ns/op 32 B/op 3 allocs/op
  3. BenchmarkDirect-8 2000000000 0.84 ns/op 0 B/op 0 allocs/op
  4. 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:

确定