Создайте массив C struct в Go - PullRequest
0 голосов
/ 13 марта 2020

Я пытаюсь вызвать C lib из Go программы, используя CGo. У меня есть следующие C файлы, которые составляют C lib. Но я получаю следующую ошибку: «cgo параметр имеет Go указатель на Go указатель». Я поражен созданием массива C struct в Go.

caller.h

enum c_callerIdType{
    user,
    certificate
}

typedef struct _c_callerid
{
    c_callerIdType type,
    char* value
}c_callerId;

typedef struct _c_requiredprops{
    char* operationName,
    CallerId* caller_id_set,
    int caller_id_set_size
}c_requiredProps;

int log_caller_details(c_requiredProps);
caller.c

#include "caller.h"

int log_caller_details(c_requiredProps* rp){
    printf("Operation name is %s", rp->operationName);
    // printf the callerid details
    return 1;
}

Я создал оболочку Go для этой библиотеки C следующим образом.

main.go

package main

// #include "caller.h"
// #include <stdlib.h>
import "C"
import "fmt"

type CallerId struct{
    type string
    value string
}

type RequiredProperties struct{
    operationName string
    callerIds []CallerId
}

// a helper function to call in to the C lib
func callCFunc() int{
    var cRequiredProps C.c_requiredProps
    var requiredProps RequiredProperties
    var userCaller CallerId
    var certCaller CallerId

    // create user caller
    userCaller.type = "user"
    userCaller.value = "user1"

    // create certificate caller
    certCaller.type ="certificate"
    certCaller.value = "service1.widgetcorp.com"

    requiredProps.operationName = "UpdateWidget"
    requiredProps.callerIds = []{userCaller,certCaller}

    // convert from Go struct to C struct
    var cOpName = C.CString(requiredProps.operationName)
    defer C.free(unsafe.Pointer(cOpName))
    cRequiredProps.operationName = cOpName

    var cCallerIds = make([]C.c_callerId, 2)

    for i,callerId := range requiredProps.callerIds{
        var cTempCallerId C.c_callerId
        cTempCallerId.type = C.c_callerIdType(callerId.type)
        var cValue = C.CString(callerId.value)
        cTempCallerId.value = cValue
        defer C.free(unsafe.Pointer(cValue))
        cCallerIds[i] = cTempCallerId
     }

    // this line throws error "CGo parameter has Go pointer to Go pointer" --> cRequiredProps.caller_id_set = (*C.c_requiredProps)  (unsafe.Pointer(&cCallerIds[0]))

    cRequiredProps.caller_id_set_size=2

    return 1
}

func main() int{
    fmt.PrintLn(callCFunc())
}

Что я делаю не так? Как создать массив C структур внутри Go и вызвать функцию C?

...