2017-03-16 88 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

谢谢,我会尝试再次调试。 –