猿问

将结构体和结构体数组从 Go 传递给 C 函数

被这个问题困住了。只能获得传递结构的第一个成员......我做错了什么?将结构从 Go 传递到 C 的正确方法是什么?


这是我如何不起作用的示例:


package main


/*

#include <stdio.h>


typedef struct {

    int a;

    int b;

} Foo;


void pass_array(Foo **in) {

    int i;


    for(i = 0; i < 2; i++) {

        fprintf(stderr, "[%d, %d]", in[i]->a, in[i]->b);

    }

    fprintf(stderr, "\n");

}


void pass_struct(Foo *in) {

    fprintf(stderr, "[%d, %d]\n", in->a, in->b);

}


*/

import "C"


import (

    "unsafe"

)


type Foo struct {

    A int

    B int

}


func main() {


    foo := Foo{25, 26}

    foos := []Foo{{25, 26}, {50, 51}}


    // wrong result = [25, 0]

    C.pass_struct((*_Ctype_Foo)(unsafe.Pointer(&foo)))


    // doesn't work at all, SIGSEGV

    // C.pass_array((**_Ctype_Foo)(unsafe.Pointer(&foos[0])))


    // wrong result = [25, 0], [50, 0]

    out := make([]*_Ctype_Foo, len(foos))

    out[0] = (*_Ctype_Foo)(unsafe.Pointer(&foos[0]))

    out[1] = (*_Ctype_Foo)(unsafe.Pointer(&foos[1]))

    C.pass_array((**_Ctype_Foo)(unsafe.Pointer(&out[0])))

}


沧海一幻觉
浏览 295回答 3
3回答

一只萌萌小番薯

问题是Foo和_Ctype_Foo是不同的结构。我猜你在 64 位上运行。请注意,intgo中是 64 位,但在 C 中很可能是 32 位。如果我将 的定义更改Foo为此,那么它可以在我的机器上运行(64 位 linux)type Foo struct {&nbsp; &nbsp; A int32&nbsp; &nbsp; B int32}但是我会说这是一个麻烦的秘诀 - 让你的 Go 和 C 代码使用相同的结构type Foo _Ctype_Foo

HUX布斯

这些答案现在都不起作用(至少在 Go 1.12 下)。我写了另外两个解决方案:package main/*#include <stdio.h>#include <stdlib.h>typedef struct {&nbsp; &nbsp; int a;&nbsp; &nbsp; int b;} Foo;int pass_array(Foo **in) {&nbsp; &nbsp; int i;&nbsp; &nbsp; int r = 0;&nbsp; &nbsp; for(i = 0; i < 2; i++) {&nbsp; &nbsp; &nbsp; &nbsp; r += in[i]->a;&nbsp; &nbsp; &nbsp; &nbsp; r *= in[i]->b;&nbsp; &nbsp; }&nbsp; &nbsp; return r;}*/import "C"import (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "unsafe")type Foo struct {&nbsp; &nbsp; A int32&nbsp; &nbsp; B int32}func a() {&nbsp; &nbsp; foos := []Foo{{1, 2}, {3, 4}}&nbsp; &nbsp; l := len(foos)&nbsp; &nbsp; values := (*[1 << 28]*C.Foo)(C.malloc(C.size_t(C.sizeof_Foo * l)))&nbsp; &nbsp; for i, f := range foos {&nbsp; &nbsp; &nbsp; &nbsp; foo := (*C.Foo)(C.malloc(C.size_t(C.sizeof_Foo)))&nbsp; &nbsp; &nbsp; &nbsp; (*foo).a = C.int(f.A)&nbsp; &nbsp; &nbsp; &nbsp; (*foo).b = C.int(f.B)&nbsp; &nbsp; &nbsp; &nbsp; values[i] = foo&nbsp; &nbsp; }&nbsp; &nbsp; val := C.pass_array(&values[0])&nbsp; &nbsp; for i := 0; i < l; i++ {&nbsp; &nbsp; &nbsp; &nbsp; C.free(unsafe.Pointer(values[i]))&nbsp; &nbsp; }&nbsp; &nbsp; C.free(unsafe.Pointer(values))&nbsp; &nbsp; fmt.Println("A finished", val)}func b() {&nbsp; &nbsp; foos := []Foo{{5, 6}, {7, 8}}&nbsp; &nbsp; values := make([]*C.Foo, len(foos))&nbsp; &nbsp; for i, f := range foos {&nbsp; &nbsp; &nbsp; &nbsp; p := (*C.Foo)(C.malloc(C.size_t(C.sizeof_Foo)))&nbsp; &nbsp; &nbsp; &nbsp; values[i] = p&nbsp; &nbsp; &nbsp; &nbsp; (*p).a = C.int(f.A)&nbsp; &nbsp; &nbsp; &nbsp; (*p).b = C.int(f.B)&nbsp; &nbsp; }&nbsp; &nbsp; val := C.pass_array(&values[0])&nbsp; &nbsp; for _, v := range values {&nbsp; &nbsp; &nbsp; &nbsp; C.free(unsafe.Pointer(v))&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println("B finished", val)}func main() {&nbsp; &nbsp; a()&nbsp; &nbsp; b()}
随时随地看视频慕课网APP

相关分类

Go
我要回答