dongzhina7098 2017-03-16 18:10
浏览 335

cgo使用c struct数组并在go中分配值

I have issue when using cgo with c struct array.

My program as follow:

I have struct in c and contain a pointer to a c struct array.

In C, I provide a initialize function (take two parameter: the pointer to the variable, the length of the array inside the variable) to malloc the memory of the variable.

Then In go, I assign the value to this variable and assign value to the array in variable. And in go , I call another C function to using this variable.

After the C function handle it. Go pick up the variable again and return to other Go function.

When I coded like this, I go a array like. type *C.struct does not support indexing.

My code like follow.

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);
}

My GO code

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")
}

When I compile in like this profiles.profile[0].profileId = C.int(2)

I got error message : invalid operation: profiles.profile[0] (type *C.struct___6 does not support indexing)

So, I try another solution. Transfer the c struct array form c to go. like this

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

But get error like cannot use (*[1073741824]C.struct___6)(unsafe.Pointer(&profiles.profile))[:numProfiles:numProfiles] (type []C.struct___6) as type *C.struct___6 in assignment

and I afraid It create another piece of memory, when I call in dosomething_In_C function, it can not get the data.

Is anyone know how to fix this?

Thank you

  • 写回答

1条回答 默认 最新

  • dqjl0906 2017-03-16 18:38
    关注

    You can't index C arrays, and you can't assign a Go slice to a C struct, but you don't need to since the new slice references the same memory region.

    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")
    
    评论

报告相同问题?

悬赏问题

  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制