I'm trying to call a function in a C++ library with a C compatible header, which wants me to pass in a 4x4 matrix for it to populate.
My Go function definition looks like this:
func GetMatrix(matrix [][]float32)
func GetMatrix(matrix []float32)
And the c header defines it like this:
void getMatrix(const float **matrix)
I've tried using C.GoBytes to get a byte array, but then from there I'm a little lost as I have to go from a byte array to an array of pointers, which I then again convert to an array of bytes, and eventually an array of floats.
At least I think that's what I need to do.
I've seen examples of code replacing the underlying Go slice with the C array data, but I believe in those cases, the Go GC won't collect them. Ideally matrix [][]float32 would behave like a normal Go slice.
Edit: The documentation was incorrect, and the underlying C type is actually a 16 element float array.
So the question then becomes, can I use C.GoBytes with a pointer, to a pointer of an array, and if so, how do I get a []float32 from []byte?
I think that the Go type you'll have to use is
*[16]*float32
In any case the [][]float32 is never going to be compatible with **float of C.
Pointer to 4x4 array of arrays has type *[4]*[4]float32
.
Edited This prints the right stuff
package main
/*
#include <stdio.h>
void getMatrix(const float **matrix){
float *m = (float *)matrix;
int i;
for(i = 0; i<9; i++) {
printf("%f
",m[i]);
}
}
*/
import "C"
import "unsafe"
func main() {
a := []float32{1,2,3,4,5,6,7,8,9}
C.getMatrix((**C.float)(unsafe.Pointer(&a[0])))
}
Extending on the answer provided by Inuart:
package main
/*
#include <stdio.h>
void getMatrix(const float **matrix){
float *m = (float *)*matrix;
int i;
for(i = 0; i<16; i++) {
printf("%f
",m[i]);
}
}
*/
import "C"
import "unsafe"
func main() {
// Create the contiguous 16 element array, but organise it how it is described.
a := [4][4]float32{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16},
}
m := &a // Take the pointer.
C.getMatrix((**C.float)(unsafe.Pointer(&m))) // Take the handle and pass it.
}
This give you the handle behaviour that you seem to be asking for and has the advantage that the shape of the data in Go is as it appears to be asked for by the C API - there's no need to eschew the ease of use and safety of Go, just because you are interfacing with C.
Here's a way to pass a pointer to a go array to a C function, so the C function can populate it:
package main
/*
#include <stdio.h>
void getMatrix(float *m) {
int i;
for(i = 0; i < 16; i++) {
m[i] = (float)i;
}
}
*/
import "C"
import "fmt"
func main() {
var a [16]float32
C.getMatrix((*C.float)(&a[0]))
fmt.Println(a)
}