Awesome! Thanks again for your kindly help. :) And I updated the code, it 
works! 

在 2017年8月8日星期二 UTC+8下午3:51:10,Konstantin Khomoutov写道:
>
> On Mon, Aug 07, 2017 at 08:20:01PM -0700, jianzh...@gmail.com 
> <javascript:> 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) 
>                   } 
>           } 
>           C.crunch_matrix(&matrix[0]) 
>   } 
>
> 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 
> slice. 
>
> 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