преобразовать [] float32 в C * float

Я хочу передать указатель на первый элемент слайса []float32 в переменную 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]) // here the program breaks

Насколько я понял, должна быть возможность напрямую передать указатель на первый элемент в срезе из Go в C без использования unsafe.Pointer().

Затем функция C будет перебирать срез (длина известна).

Любые подсказки приветствуются!


person dh1tw    schedule 17.11.2016    source источник


Ответы (1)


  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 в выделенной структуре Go, переданной в Cgo:
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]
}

В качестве альтернативы вы можете выделить и освободить структуру SRC_DATA в C:

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]
}
person KAdot    schedule 17.11.2016