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.

Reply via email to