2017-03-16 38 views
1

我有問題時使用cgo與c結構數組。cgo使用c結構數組並在去分配值

我的如下程序:

我在C結構和包含一個指向一個C結構陣列。

在C中,我提供了一個初始化函數(取兩個參數:指向變量的指針,變量內部數組的長度)給malloc變量的內存。

然後在go中,我將值賦給這個變量,並賦值給變量中的數組。然後,我會調用另一個C函數來使用這個變量。

C函數處理它之後。再次選取變量並返回其他Go功能。

當我編碼像這樣,我去了一個數組。鍵入* C.struct不支持索引。

我的代碼如下。

C:

test.h

typedef struct 
{ 
    int  profileCnt; 
    _profile *profile;      //pointer to profile array 
}_profiles; 
// variable using in Go 


typedef struct 
{ 
    int  profileId;    
    _name userName;    
    char   *dateOfBirth;   
    int  stateFipsId;    
}_profile; 

typedef struct 
{ 
    char first[32]; 
    char last[32]; 
} _name; 


void initializeProfiles(_profiles *profiles, int profileCount, bool create); 
int doSomething _In_C(_profiles *profiles, int log); 

test.c的

void initializeProfiles(_profiles *profiles, int profileCount, bool create) 
{ 

    profiles->profileCnt = profileCount;             
// initialize profiles struct & profile[] Array 

    if (profileCount > 0) 
    { 
     if (create == true) 
      profiles->profile = malloc(profileCount * sizeof *profiles->profile + 1);   // allocate memory for profiles[numProfiles] 

      for (int i = 0; i < profiles->profileCnt; i++) 
      initializeProfile(&profiles->profile[i], create); 

     if (create == false) 
     { 
      free(profiles->profile); 
      profiles->profileCnt = 0; 
     } 
    } 
    else 
     profiles->profile = NULL; 

} 

void initializeProfile(_profile *profile, bool create) 
{ 
    if (create == true) 
    {  
     profile->dateOfBirth = NULL;    
    } 

    profile->profileId = 0;     
    memset(profile->userName.first, '\0', sizeof(profile->userName.first));  
    memset(profile->userName.last, '\0', sizeof(profile->userName.last));  

    if (create == false) 
    { 
     if (profile->dateOfBirth != NULL) 
      free(profile->dateOfBirth); 
    } 
} 



int doSomething _In_C(_profiles *profiles, int log) 
{ 

    /* =========================================== 



    */ ==== did something to that variable============================ 

    if (errStatus.code == _SUCCESS) 
     return(_SUCCESS); 
    else 
     return(FAILURE); 
} 

我的GO代碼

package main 
//#cgo CFLAGS: -std=c99 -ggdb3 -O0 -Wall 
//#cgo CFLAGS: -I../../include/common 
//#cgo LDFLAGS: -L string.h 
//#cgo LDFLAGS: -lstdc++ -lpthread -lm -lc -lssl -lcrypto 
//#include <stdio.h> 
//#include <stdlib.h> 
//#include "test.h" 
import "C" 


//import "unsafe" 

func Test() { 

    log := 1 // sets logging level 
    numProfiles := 3 

    var profiles C._profiles 

    C.initializeProfiles(&profiles, C.int(numProfiles), C.bool(true)) 


    profiles.profile[0].profileId = C.int(2) 
    profiles.profile[0].stateFipsId = C.int(1) 
    profiles.profile[0].userName.first = C.CString("test") 
    profiles.profile[0].userName.last = C.CString("test") 

    C.dosomething_In_C(&profiles,C.int(3)) 

    C.initializeProfiles(&profiles, C.int(numProfiles), C.bool(false)) 


    fmt.Println(int("get c variable and return") 
} 

當我編譯在這樣 profiles.profi勒[0] = .profileId C.int(2)

我得到錯誤消息: 無效操作:profiles.profile [0](類型* C.struct ___ 6不支持索引)

所以,我嘗試其他解決方案傳遞c結構數組形式c去。這樣

profile.profikes = (*[1 << 30]C._profile)(unsafe.Pointer(&profiles.profile))[:numProfiles:numProfiles] 

但是,像不能用得到錯誤(* [1073741824] C.struct ___ 6)(unsafe.Pointer(& profiles.profile)):numProfiles:numProfiles(鍵入[] C.struct ___ 6)鍵入* C.struct ___ 6賦值

我恐怕會創建另一塊內存,當我在dosomething_In_C函數中調用時,它無法獲取數據。

有人知道如何解決這個問題嗎?

謝謝你

回答

0

你不能索引C數組,你不能指定一個圍棋切片是一種C結構,但是你並不需要,因爲新的片引用相同的內存區域。

p := (*[1 << 30]C._profile)(unsafe.Pointer(profiles.profile))[:numProfiles:numProfiles] 

p[0].profileId = C.int(2) 
p[0].stateFipsId = C.int(1) 
p[0].userName.first = C.CString("test") 
p[0].userName.last = C.CString("test") 
+0

謝謝JimB。其實,我需要參考相同的記憶。因爲初始化和賦值後我需要傳遞給另一個C函數作爲參數。一旦我使用具有固定長度數組結構的C結構,它就支持索引。我可以直接賦值,如profies.profile [0] .profileId = C.int(2)。但是,何時可以動態長度數組它不能。 –

+0

@weiZhang:我不明白。我說這個_does_引用了相同的內存,並且沒有什麼能阻止你將指針傳遞迴C函數。這只是讓你用Go的索引符號訪問數組值。 – JimB

+0

謝謝,我會嘗試再次調試。 –