On Tue, Jan 28, 2020 at 4:44 AM mark mellar <radiatorf...@gmail.com> wrote: > > Hi Folks, I'm having some trouble instantiating a C struct from a 3rd party > API. > > I'm not sure if this is more a C question or a Go question, details in the > code below, any help would be much appreciated! > > M > > // This non-compiling example demonstrates an issue I'm having integrating a > 3rd party C api with my Go code > // The comment preceding 'import "C"' constitutes C code which is interpreted > as a header when compiling. > // 'api_struct' represents the 3rd party struct I'm attempting to instantiate > and populate in my Go Code > // we cannot make changes to this struct > // other c functions in the comment are helper functions I've written to > instantiate certain C types > > // The go code defines an array of strings and an array of ints. For each of > these arrays a helper > // function is called to create a C array of the C equivalent type before > populating that array. > // Once C arrays have been populated they are assigned to fields in the a new > api_struct. > > // This method works fine for the string array, but compile fails when we get > to the int array > // This is because makeIntArray returns *_Ctype_int but api_struct.rLimits > expects [12]_Ctype_int. Here's the error... > // cannot use cInts (type *_Ctype_int) as type [12]_Ctype_int in field value > > // I'd like to modify makeIntArray to return a [12]_Ctype_int but I can't > seem to find the right syntax to achieve this > package main > > /* > #define ARRLEN 12 > #include <stdlib.h> > > struct api_struct { > char **askedHosts; > int rLimits[ARRLEN]; > }; > > static char**makeCharArray(int size) { > return calloc(sizeof(char*), size); > } > > static void setArrayString(char **a, char *s, int n) { > a[n] = s; > } > > static void freeCharArray(char **a, int size) { > int i; > for (i = 0; i < size; i++) > free(a[i]); > free(a); > } > > static int*makeIntArray() { > int* p = malloc(sizeof(p) * ARRLEN); > return p; > } > > static void setArrayInt(int *a, int s, int n) { > a[n] = s; > } > > static void freeIntArray(int *a, int size) { > free(a); > } > > > */ > import "C" > import "fmt" > > func main() { > goHosts := []string{"host1", "host2", "host3"} > cHosts := C.makeCharArray(C.int(len(goHosts))) > for i, s := range goHosts { > C.setArrayString(cHosts, C.CString(s), C.int(i)) > } > > goLimits := []int{1,2,3,4,5,6,7,8,9,10,11,12} > cInts := C.makeIntArray() > for i, s := range goLimits { > C.setArrayInt(cInts, C.int(s), C.int(i)) > } > > s := C.struct_api_struct{ > askedHosts: cHosts, > rLimits: cInts, > } > fmt.Printf("%+v\n", s) > }
The easy, and likely more efficient, way is to just set the rLimits field element by element. There is no safe way to convert from a *C.int to a [12]C.int in Go. You can do it easily enough using unsafe. a := *(*[12]C.int)(unsafe.Pointer(p)) This is of course only safe if p does in fact point to 12 C.int values. Ian -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAOyqgcXsdWfWP%3D_sdWkZs%2BWrcx4wCXN7qHMugTBhoE5%3DjKW_Lw%40mail.gmail.com.