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.