有没有一种安全的方法来保持使用CGo从C代码引用Go变量?

时间:2013-12-03 22:31:16

标签: garbage-collection go cgo

当使用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))
}

C代码:

#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->chfoo_new来电之间,我是否冒被垃圾收集器释放foo_send的风险?如果是这样,有没有办法从C端固定Go变量,以防止在我持有对它的引用时释放它?

1 个答案:

答案 0 :(得分:3)

根据gmp CGo example

  

垃圾收集是一个大问题。这对Go世界来说很好   有指向C世界并在它们时释放那些指针   不再需要了。为了提供帮助,Go代码可以定义Go对象   持有C指针并对那些Go对象使用runtime.SetFinalizer。

     

C世界更难以指向Go   世界,因为Go垃圾收集器不知道内存   由C.分配。最重要的考虑因素不是   约束未来的实现,因此规则是Go代码可以   指向C代码的Go指针但必须单独安排   转到挂起指针的引用,直到C完成它。

所以我不确定你是否可以从C端固定变量,但是你可以使用runtime.SetFinalizer函数控制来自Go端的变量的垃圾收集。

希望有所帮助。