On Mon, Aug 07, 2017 at 08:20:01PM -0700, jianzhang...@gmail.com wrote:

> > > > >     golevelmatrix := [][]int{{1}, {3, 3}, {3, 3, 2}} 
> > > > >    levelmatrix := make([][]C.int, len(golevelmatrix)) 
> > > > >    for i, _ := range golevelmatrix { 
> > > > >        levelmatrix[i] = make([]C.int, len(golevelmatrix[i])) 
> > > > >        for j, _ := range golevelmatrix[i] { 
> > > > >            levelmatrix[i][j] = C.int(golevelmatrix[i][j]) 
> > > > >        } 
> > > > >    } 
> > [...] 
> >
> > I'd like to reiterate more precisely: your client is expecting a 
> > multi-dimensional array which, in C, would be a contiguous region of 
> > memory.  The Go's [][]C.int is a slice of individual []C.int slices. 
> > Hence when you pass &levelmatrix[0][0] to your C client, it receives the 
> > address of the first element of the first slice, and the only valid 
> > region of memory to access via that pointer is that element and all the 
> > element following it up to (but not including) the length of the first 
> > slice. 
> But, if I can not change the C client, how to implement it? the C client as 
> the following. As described on the above, I have to change the ` int**
>  _levelmatrix` argument, right?
> bool test_settopologyresource(bsagomodule* _self, char* _nodename,
>        int _resourceindex, char** _nameunits, int** _levelmatrix) {
>    printf("\n set topology resource-> node:%s, resource index:%d", _nodename
> , _resourceindex);
>    bool result = settopologyresource(_self->client, _nodename, 
> _resourceindex, _nameunits, _levelmatrix);
>    return result;
> }

Ah, I see.

So, do I understand correctly that your C side is actually expecting
an "array of arrays" (or "jagged array" as some call them)?
That would explain the int** type your function expects.

If yes, this is doable without changing the C side -- by C.malloc()'ing
each member array and storing the pointer to it in the main array:

  package main
  import "unsafe"
  extern int crunch_matrix(int **a);
  import "C"
  func main() {
        golevelmatrix := [][]int{{1}, {3, 3}, {3, 3, 2}}
        matrix := make([]*C.int, len(golevelmatrix))
        for i, row := range golevelmatrix {
                p := (*C.int)(C.malloc(C.size_t(C.sizeof_int * len(row))))
                matrix[i] = p
                pa := (*[1 << 30]C.int)(unsafe.Pointer(p))
                for j, v := range row {
                        (*pa)[j] = C.int(v)

Here, for each row of the source matrix we allocate an array of C.int of
the source row's size, and place a pointer to it into the destination

To fill the allocated row array with the source values without jumping
through the hoops of direct pointer arithmetics, we type-convert the
value of "p" (which has type *C.int) to the type *[1 << 30]C.int which
is a pointer to a very long array of C.int (read more on this in the
section "Turning C arrays into Go slices" in [1]).

Note two problems with this approach.

First, I made no effort to free the memory obtained by calls to
C.malloc().  That's mostly for brewity, but see below.

Second, as the code stands now, as soon as we allocate an array for the
target row, the information of its size is lost.  We can safely pass the
pointer to it to C.free (because C.malloc stores a special block of
information along with each block it allocates which contains the length
of that block) but I fail to see how your C side is aware of the length
of each row array.  On the Go side, the matrix is a slice of slices, and
since a Go slice is fully self-aware, that's OK but in C, an array is
merely a pointer, and it carries no information of the length of the
memory block pointed to by that pointer.

Hence, unless I fail to spot where you encode this information in
the arguments supplied to test_settopologyresource(), this might
indicate a problem with your design of your C side: you might need to
either use a custom type for the rows of your C matrix (a struct
containing a pointer and a size, for instance) or operate on full square
matrices as in my first example.

1. https://github.com/golang/go/wiki/cgo

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.
For more options, visit https://groups.google.com/d/optout.

Reply via email to