为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
沧海一幻觉 2021-06-30 09:11:21
被这个问题困住了。只能获得传递结构的第一个成员......我做错了什么?将结构从 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])))}
查看完整描述

3 回答

?
一只萌萌小番薯

TA贡献1795条经验 获得超7个赞

问题是Foo和_Ctype_Foo是不同的结构。


我猜你在 64 位上运行。请注意,intgo中是 64 位,但在 C 中很可能是 32 位。


如果我将 的定义更改Foo为此,那么它可以在我的机器上运行(64 位 linux)


type Foo struct {

    A int32

    B int32

}

但是我会说这是一个麻烦的秘诀 - 让你的 Go 和 C 代码使用相同的结构


type Foo _Ctype_Foo


查看完整回答
反对 回复 2021-07-12
?
HUX布斯

TA贡献1876条经验 获得超6个赞

这些答案现在都不起作用(至少在 Go 1.12 下)。我写了另外两个解决方案:


package main


/*

#include <stdio.h>

#include <stdlib.h>


typedef struct {

    int a;

    int b;

} Foo;


int pass_array(Foo **in) {

    int i;

    int r = 0;


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

        r += in[i]->a;

        r *= in[i]->b;

    }

    return r;

}


*/

import "C"

import (

    "fmt"

    "unsafe"

)


type Foo struct {

    A int32

    B int32

}


func a() {

    foos := []Foo{{1, 2}, {3, 4}}


    l := len(foos)

    values := (*[1 << 28]*C.Foo)(C.malloc(C.size_t(C.sizeof_Foo * l)))

    for i, f := range foos {

        foo := (*C.Foo)(C.malloc(C.size_t(C.sizeof_Foo)))

        (*foo).a = C.int(f.A)

        (*foo).b = C.int(f.B)

        values[i] = foo

    }

    val := C.pass_array(&values[0])

    for i := 0; i < l; i++ {

        C.free(unsafe.Pointer(values[i]))

    }

    C.free(unsafe.Pointer(values))

    fmt.Println("A finished", val)

}


func b() {

    foos := []Foo{{5, 6}, {7, 8}}


    values := make([]*C.Foo, len(foos))

    for i, f := range foos {

        p := (*C.Foo)(C.malloc(C.size_t(C.sizeof_Foo)))

        values[i] = p

        (*p).a = C.int(f.A)

        (*p).b = C.int(f.B)

    }

    val := C.pass_array(&values[0])

    for _, v := range values {

        C.free(unsafe.Pointer(v))

    }

    fmt.Println("B finished", val)

}


func main() {

    a()

    b()

}



查看完整回答
反对 回复 2021-07-12
  • 3 回答
  • 0 关注
  • 281 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信