2017-04-27 18 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