将一个切片从C语言传递给Go语言时,是否会进行内存复制?

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

Does passing a slice to golang from c do a memory copy?

问题

我需要将一个大块的float32(或byte)数据从C传递给一个Go库。

以下是代码:

  1. package main
  2. import (
  3. "C"
  4. "fmt"
  5. )
  6. //export PrintInt
  7. func PrintInt(x []float32) {
  8. fmt.Println(x)
  9. }
  10. func main() {}

使用go build -buildmode=c-archive foo.go编译后,我得到了foo.h,以下是其中的一部分内容:

  1. typedef GoInt64 GoInt;
  2. typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
  3. #endif
  4. /* End of boilerplate cgo prologue. */
  5. #ifdef __cplusplus
  6. extern "C" {
  7. #endif
  8. extern void PrintInt(GoSlice p0);
  9. #ifdef __cplusplus
  10. }
  11. #endif

你可以看到,在foo.h中,类型GoSlice持有一个指向数据的指针(void *data)。那么,在foo.h中的PrintInt实现是否对该数据进行了隐式复制?

英文:

I need to pass a big chunk for float32 (or byte) from C to a go library.

Here is the code:

  1. package main
  2. import (
  3. "C"
  4. "fmt"
  5. )
  6. //export PrintInt
  7. func PrintInt(x []float32) {
  8. fmt.Println(x)
  9. }
  10. func main() {}

After compile it with go build -buildmode=c-archive foo.go

I got foo.h, here of a part of it:

  1. typedef GoInt64 GoInt;
  2. typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
  3. #endif
  4. /* End of boilerplate cgo prologue. */
  5. #ifdef __cplusplus
  6. extern "C" {
  7. #endif
  8. extern void PrintInt(GoSlice p0);
  9. #ifdef __cplusplus
  10. }
  11. #endif

You can see that type GoSlice in foo.h holds a pointer to the data (void *data). So does the implementation of PrintInt in foo.h do an implicit copy of that data?

答案1

得分: 3

我尝试在Go端修改数据,然后在C端进行反映。所以它们共享同一块内存。

foo.go:

  1. package main
  2. import (
  3. "C"
  4. "fmt"
  5. )
  6. //export PrintInt
  7. func PrintInt(x []float32) {
  8. fmt.Println(x)
  9. for i := range x {
  10. x[i] = -float32(i)
  11. }
  12. }
  13. func main() {}

foo.c:

  1. #include <stdio.h>
  2. #include "foo.h"
  3. int main() {
  4. float bar[32];
  5. for(int i = 0; i < 32; i++) {
  6. bar[i] = i;
  7. }
  8. GoSlice s;
  9. s.data = (void*)bar;
  10. s.len = 32;
  11. s.cap = 32;
  12. PrintInt(s);
  13. for(int i = 0; i < 32; i++) {
  14. printf("%f ", bar[i]);
  15. }
  16. return 0;
  17. }

使用以下命令编译和运行:

  1. go build -buildmode=c-archive foo.go
  2. cc foo.c foo.a -o 123 && ./123

我得到的输出是:

[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
26 27 28 29 30 31]
-0.000000 -1.000000 -2.000000 -3.000000 -4.000000 -5.000000 -6.000000 -7.000000 -8.000000 -9.000000 -10.000000 -11.000000 -12.000000 -13.000000 -14.000000 -15.000000 -16.000000 -17.000000 -18.000000 -19.000000 -20.000000 -21.000000 -22.000000 -23.000000 -24.000000 -25.000000 -26.000000 -27.000000 -28.000000 -29.000000 -30.000000 -31.000000

英文:

I tried to modify the data from go side, it is reflected in C. So they share same memory.

foo.go:

  1. package main
  2. import (
  3. &quot;C&quot;
  4. &quot;fmt&quot;
  5. )
  6. //export PrintInt
  7. func PrintInt(x []float32) {
  8. fmt.Println(x)
  9. for i := range x {
  10. x[i] = -float32(i)
  11. }
  12. }
  13. func main() {}

foo.c:

  1. #include &lt;stdio.h&gt;
  2. #include &quot;foo.h&quot;
  3. int main() {
  4. float bar[32];
  5. for(int i = 0; i &lt; 32; i++) {
  6. bar[i] = i;
  7. }
  8. GoSlice s;
  9. s.data = (void*)bar;
  10. s.len = 32;
  11. s.cap = 32;
  12. PrintInt(s);
  13. for(int i = 0; i &lt; 32; i++) {
  14. printf(&quot;%f &quot;, bar[i]);
  15. }
  16. return 0;
  17. }

With command:

  1. go build -buildmode=c-archive foo.go
  2. cc foo.c foo.a -o 123 &amp;&amp; ./123

I got output:

> [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
> 26 27 28 29 30 31]
> -0.000000 -1.000000 -2.000000 -3.000000 -4.000000 -5.000000 -6.000000 -7.000000 -8.000000 -9.000000 -10.000000 -11.000000 -12.000000 -13.000000 -14.000000 -15.000000 -16.000000 -17.000000 -18.000000 -19.000000 -20.000000 -21.000000 -22.000000 -23.000000 -24.000000 -25.000000 -26.000000 -27.000000 -28.000000 -29.000000 -30.000000 -31.000000

huangapple
  • 本文由 发表于 2017年4月27日 08:15:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/43646589.html
匿名

发表评论

匿名网友

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

确定