【问题标题】:Does passing a slice to golang from c do a memory copy?将切片从 c 传递给 golang 是否会进行内存复制?
【发布时间】:2017-04-27 09:06:13
【问题描述】:

我需要将一个大块的 float32(或字节)从 C 传递到 go 库。

代码如下:

package main

import (
        "C"
        "fmt"
)

//export PrintInt                                                                                                     
func PrintInt(x []float32) {
        fmt.Println(x)
}

func main() {}

go build -buildmode=c-archive foo.go编译后

我收到了foo.h,这是其中的一部分:

typedef GoInt64 GoInt;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

/* End of boilerplate cgo prologue.  */

#ifdef __cplusplus
extern "C" {
#endif


extern void PrintInt(GoSlice p0);

#ifdef __cplusplus
}
#endif

您可以看到foo.h 中的类型GoSlice 持有指向数据的指针(void *data)。那么PrintIntfoo.h 中的实现是否会隐式复制该数据?

【问题讨论】:

  • 如何将切片从 C 传递到 Go?如果你在 C 中创建切片头,答案应该很明显,因为切片头包含指向底层数组的指针。
  • @JimB 你可能是对的,这是最合理的实现。但是接口并没有禁止实现复制。
  • 不会发生这种情况。 C 和 Go 都不会隐式分配新内存、复制相关数组并将 不同 值传递给函数。 Go 在所有情况下都是按值传递的,这里的值是切片头,没有别的。
  • @JimB "C 和 Go 都不会隐式分配新内存" 你能告诉我这是否记录在某处吗?我想确定下次遇到类似问题时。
  • 我认为如果内存被复制,结构会有所不同,因为指针值必须改变。将值传递给函数并让函数接收 不同 值会很奇怪。您是否期望传递一个普通指针来取消引用并递归复制每个值,然后以某种方式在函数中接收一个新指针?一种语言实现可以做的事情有无数种,但并不是每一种可能性都可以记录下来。

标签: go cgo


【解决方案1】:

我尝试从 go 端修改数据,它反映在 C 中。所以它们共享相同的内存。

foo.go:

package main

import (
    "C"
    "fmt"
)

//export PrintInt
func PrintInt(x []float32) {
    fmt.Println(x)
    for i := range x {
        x[i] = -float32(i)
    }
}

func main() {}

foo.c:

#include <stdio.h>

#include "foo.h"

int main() {
  float bar[32];
  for(int i = 0; i < 32; i++) {
    bar[i] = i;
  }

  GoSlice s;
  s.data = (void*)bar;
  s.len = 32;
  s.cap = 32;
  PrintInt(s);

  for(int i = 0; i < 32; i++) {
    printf("%f ", bar[i]);
  }

  return 0;
}

使用命令:

go build -buildmode=c-archive foo.go
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.000000000000000000000000000000000000000000000000000000000000000000000000000000000000来客-5.000000000000000000000000000000000000000000000000000000来-25.000000 -26.000000 -27.000000 -28.000000 -29.000000 -30.000000 -31.000000

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-09
    • 2018-06-15
    • 2019-02-25
    相关资源
    最近更新 更多