2017-04-27 206 views
0

我需要将float32(或字节)的大块从C传递给go库。从c传递片段给golang做内存拷贝?

下面是代码:

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 

你可以看到,类型GoSlicefoo.h包含指向数据的指针(void *data)。那么foo.h中的PrintInt的实现是否会执行该数据的隐式副本?

+0

你是如何从C到Go的切片?如果你在C中创建切片头,答案应该很明显,因为切片头包含指向底层数组的指针。 – JimB

+0

@JimB你可能是对的,这是最合理的实现。但界面并不禁止执行复制。 –

+0

不会有这种情况发生。 C和Go都不会隐式分配新内存,复制相关数组,并将_different_值传递给函数。 Go在所有情况下都是按值传递的,这里的值是切片头,没有别的。 – JimB

回答

1

我试图修改从旁边的数据,它反映在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.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