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) } } 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.