Search code examples
cgocatboostcatboostregressor

Passing a Go slice of float32 to CGo as a C float[]


I'm trying to use catboost to predict for one array of floats.

In the documentation for CalcModelPredictionSingle it takes as param "floatFeatures - array of float features": https://github.com/catboost/catboost/blob/master/catboost/libs/model_interface/c_api.h#L175

However when I try to pass an array of floats, I get this error:

Cannot use type []*_Ctype_float as *_Ctype_float in assignment.

Indicating it's expecting a single float. Am I using the wrong function?

I am using cgo and this is part of my code:

```
floats := []float32{}
//gets populated

floatsC := make([]*C.float, len(floats))
for i, v := range floats {
    floatsC[i] = (*C.float)(&v)
}

if !C.CalcModelPredictionSingle(
    model.Handle,
    ([]*C.float)(floatsC),
    ...
) {
    return
}

Solution

  • The API is expecting an array of floats, but []*C.float that you're trying to make is an array of pointers-to-floats. Those are incompatible types, which is exactly what the compiler is telling.

    The good news is none of that is necessary as a Go []float32 is layout-compatible with a C float[] so you can pass your Go slice directly to the C function as a pointer to its first element.

    floats := []float32{}
    //gets populated
        
    if !C.CalcModelPredictionSingle(
        model.Handle,
        (*C.float)(&floats[0]), // pass the pointer to the first slice element
        C.size_t(len(floats)),  // pass the slice length
        ...
    ) {
        return
    }
    

    Note that in C float[] and *float are the same thing.