猿问

有没有一种安全的方法可以使用 CGo 从 C 代码中保留对 Go 变量的引用?

当使用 CGo 将 C 代码与 Go 接口时,如果我在 C 端保留对 Go 变量的引用,我是否会冒该对象被垃圾收集器释放的风险,或者 GC 是否会看到由管理的变量中的指针? C面?


为了说明我的要求,请考虑以下示例程序:


去代码:


package main


/*

typedef struct _Foo Foo;

Foo *foo_new(void);

void foo_send(Foo *foo, int x);

int foo_recv(Foo *foo);

*/

import "C"


//export makeChannel

func makeChannel() chan int {

    return make(chan int, 1)

}


//export sendInt

func sendInt(ch chan int, x int) {

    ch <- x

}


//export recvInt

func recvInt(ch chan int) int {

    return <-ch

}


func main() {

    foo := C.foo_new()

    C.foo_send(foo, 42)

    println(C.foo_recv(foo))

}

代码:


#include <stdlib.h>

#include "_cgo_export.h"


struct _Foo {

    GoChan ch;

};


Foo *foo_new(void) {

    Foo *foo = malloc(sizeof(Foo));

    foo->ch = makeChannel();

    return foo;

}


void foo_send(Foo *foo, int x) {

    sendInt(foo->ch, x);

}


int foo_recv(Foo *foo) {

    return recvInt(foo->ch);

}

foo->ch在foo_new和foo_send调用之间是否有被垃圾收集器释放的风险?如果是这样,有没有办法从 C 端固定 Go 变量以防止它在我持有对它的引用时被释放?


紫衣仙女
浏览 241回答 1
1回答

千巷猫影

根据gmp CGo 示例:垃圾收集是个大问题。Go 世界拥有指向 C 世界的指针并在不再需要时释放这些指针是很好的。为了提供帮助,Go 代码可以定义包含 C 指针的 Go 对象,并在这些 Go 对象上使用 runtime.SetFinalizer。C 世界有指向 Go 世界的指针要困难得多,因为 Go 垃圾收集器不知道 C 分配的内存。最重要的考虑是不限制未来的实现,所以规则是 Go 代码可以传递一个指向 C 代码的 Go 指针,但必须单独安排 Go 挂起对指针的引用,直到 C 完成它。所以我不确定你是否可以从 C 端固定变量,但你可以通过使用该runtime.SetFinalizer函数从 Go 端控制变量的垃圾收集。希望有帮助。
随时随地看视频慕课网APP

相关分类

Go
我要回答