将 []float32 转换为 C *float。

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

convert a []float32 to C *float

问题

我想将一个切片 []float32 的第一个元素的指针传递给一个 C 变量,但是我不知道该怎么做。

C 代码:

typedef struct
{
    const float *data_in;
    float *data_out;
} SRC_DATA;

Go 代码:

mySlice := make([]float32, 20)
foo := C.SRC_DATA{}
foo.data_in = (*C.float)(&mySlice[0]) // 这里程序出错

据我所了解,应该可以直接将切片中的第一个元素的指针从 Go 传递给 C,而不需要使用 unsafe.Pointer()。

然后,C 函数将遍历该切片(长度已知)。

如果有任何提示,我将不胜感激!

英文:

I want to pass the pointer to the first element of a slice []float32 to a C variable, but somehow I can't figure out how.

C Code:

typedef struct
{	const float	*data_in ;
	float	 *data_out ;

} SRC_DATA ;

Go:

mySlice := make([]float32, 20)
foo := C.SRC_DATA{}
foo.data_in = *C.float(&mySlice[0]) // here the program breaks

As far as I have understood, it should be possible to pass directly a pointer to the first element in the slice from Go to C, without using unsafe.Pointer().

The C function will then iterate over the slice (length known).

Any hints are appreciated!

答案1

得分: 3

  1. 你需要使用C.float类型的切片而不是float32类型的切片:
package main

/*
#include <stdio.h>
void test(float *in) {
    printf("C %f %f\n", in[0], in[1]);
}
*/
import "C"

func main() {
    in := []C.float{1.23, 4.56}
    C.test(&in[0]) // C 1.230000 4.560000
}
  1. Go不允许将Go指针存储在传递给Cgo的Go分配的结构中:
package main

/*
#include <stdio.h>
typedef struct {
        float *in;
        float *out;
} SRC_DATA;

void test(SRC_DATA *data) {
    printf("C %f %f\n", data->in[0], data->in[1]);
    data->out[0] = 8.8;
    data->out[1] = 9.9;
}
*/
import "C"
import "fmt"

func main() {
    in := []C.float{1.23, 4.56}
    out := make([]C.float, 2)
    data := &C.SRC_DATA{in: &in[0], out: &out[0]}
    C.test(data) // panic: runtime error: cgo argument has Go pointer to Go pointer
    fmt.Println("Go", out)
}

但是你可以在C中创建一个辅助函数:

package main

/*
#include <stdio.h>
typedef struct {
        float *in;
        float *out;
} SRC_DATA;

void test(SRC_DATA *data) {
    printf("C %f %f\n", data->in[0], data->in[1]);
    data->out[0] = 8.8;
    data->out[1] = 9.9;
}

void test_helper(float *in, float *out) {
    SRC_DATA data;
    data.in = in;
    data.out = out;
    test(&data);
}
*/
import "C"
import "fmt"

func main() {
    in := []C.float{1.23, 4.56}
    out := make([]C.float, 2)
    C.test_helper(&in[0], &out[0]) // C 1.230000 4.560000
    fmt.Println("Go", out) // Go [8.8 9.9]
}

或者你可以在C中分配和释放SRC_DATA结构:

package main

/*
#include <stdio.h>
#include <stdlib.h>
typedef struct {
        float *in;
        float *out;
} SRC_DATA;

void test(SRC_DATA *data) {
    printf("C %f %f\n", data->in[0], data->in[1]);
    data->out[0] = 8.8;
    data->out[1] = 9.9;
}

SRC_DATA *alloc_src_data() {
    return (SRC_DATA*)malloc(sizeof(SRC_DATA));
}

void free_src_data(SRC_DATA *p) {
    free(p);
}
*/
import "C"
import "fmt"

func main() {
    in := []C.float{1.23, 4.56}
    out := make([]C.float, 2)
    data := C.alloc_src_data()
    defer C.free_src_data(data)
    data.in = &in[0]
    data.out = &out[0]
    C.test(data)  // C 1.230000 4.560000
    fmt.Println("Go", out)  // Go [8.8 9.9]
}
英文:
  1. You need to use a slice of C.float type instead of float32:

<!-- language: go -->

package main
/*
#include &lt;stdio.h&gt;
void test(float *in) {
    printf(&quot;C %f %f\n&quot;, in[0], in[1]);
}
*/
import &quot;C&quot;

func main() {
    in := []C.float{1.23, 4.56}
    C.test(&amp;in[0]) // C 1.230000 4.560000
}
  1. Go doesn't allow to store a Go pointer in a Go allocated structure passed to Cgo:

<!-- language: go -->

package main
/*
#include &lt;stdio.h&gt;
typedef struct {
        float *in;
        float *out;
} SRC_DATA;

void test(SRC_DATA *data) {
    printf(&quot;C %f %f\n&quot;, data-&gt;in[0], data-&gt;in[1]);
    data-&gt;out[0] = 8.8;
    data-&gt;out[1] = 9.9;
}
*/
import &quot;C&quot;
import &quot;fmt&quot;

func main() {
    in := []C.float{1.23, 4.56}
    out := make([]C.float, 2)
    data := &amp;C.SRC_DATA{in: &amp;in[0], out: &amp;out[0]}
    C.test(data) // panic: runtime error: cgo argument has Go pointer to Go pointer
    fmt.Println(&quot;Go&quot;, out)
}

But you can create a helper function in C:

<!-- language: go -->

package main
/*
#include &lt;stdio.h&gt;
typedef struct {
        float *in;
        float *out;
} SRC_DATA;

void test(SRC_DATA *data) {
    printf(&quot;C %f %f\n&quot;, data-&gt;in[0], data-&gt;in[1]);
    data-&gt;out[0] = 8.8;
    data-&gt;out[1] = 9.9;
}

void test_helper(float *in, float *out) {
    SRC_DATA data;
    data.in = in;
    data.out = out;
    test(&amp;data);
}
*/
import &quot;C&quot;
import &quot;fmt&quot;

func main() {
    in := []C.float{1.23, 4.56}
    out := make([]C.float, 2)
    C.test_helper(&amp;in[0], &amp;out[0]) // C 1.230000 4.560000
    fmt.Println(&quot;Go&quot;, out) // Go [8.8 9.9]
}

Alternatively you can allocate and free SRC_DATA structure in C:

<!-- language: go -->

package main
/*
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
typedef struct {
        float *in;
        float *out;
} SRC_DATA;

void test(SRC_DATA *data) {
    printf(&quot;C %f %f\n&quot;, data-&gt;in[0], data-&gt;in[1]);
    data-&gt;out[0] = 8.8;
    data-&gt;out[1] = 9.9;
}

SRC_DATA *alloc_src_data() {
    return (SRC_DATA*)malloc(sizeof(SRC_DATA));
}

void free_src_data(SRC_DATA *p) {
    free(p);
}
*/
import &quot;C&quot;
import &quot;fmt&quot;


func main() {
    in := []C.float{1.23, 4.56}
    out := make([]C.float, 2)
    data := C.alloc_src_data()
    defer C.free_src_data(data)
    data.in = &amp;in[0]
    data.out = &amp;out[0]
    C.test(data)  // C 1.230000 4.560000
    fmt.Println(&quot;Go&quot;, out)  // Go [8.8 9.9]
}

huangapple
  • 本文由 发表于 2016年11月17日 09:05:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/40645080.html
匿名

发表评论

匿名网友

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

确定