将一个Go的float32切片传递给CGo作为C的float[]。

huangapple go评论75阅读模式
英文:

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

问题

我正在尝试使用CatBoost来预测一个浮点数数组。

CalcModelPredictionSingle的文档中,它的参数"floatFeatures - array of float features"
https://github.com/catboost/catboost/blob/master/catboost/libs/model_interface/c_api.h#L175

然而,当我尝试传递一个浮点数数组时,我得到了这个错误:

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

这表明它期望一个单个的浮点数。我是否使用了错误的函数?

我正在使用cgo,以下是我的代码的一部分:

floats := []float32{}
//被填充

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
}
英文:

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
}

</details>


# 答案1
**得分**: 3

API期望一个`float`数组,但你尝试创建的`[]*C.float`是一个指向`float`的指针数组。这些是不兼容的类型,这正是编译器所提示的。

好消息是,这些都是不必要的,因为Go的`[]float32`与C的`float[]`具有相同的布局兼容性,所以你可以直接将Go切片作为指向其第一个元素的指针传递给C函数。

    floats := []float32{}
    //填充切片
        
    if !C.CalcModelPredictionSingle(
        model.Handle,
        (*C.float)(&floats[0]), // 将指向切片第一个元素的指针传递
        C.size_t(len(floats)),  // 传递切片长度
        ...
    ) {
        return
    }

请注意,在C中,`float[]`和`*float`是相同的东西。

<details>
<summary>英文:</summary>

The API is expecting an array of `float`s, but `[]*C.float` that you&#39;re trying to make is an array of pointers-to-`float`s. 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)(&amp;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.

</details>



huangapple
  • 本文由 发表于 2021年10月19日 23:15:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/69633493.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定