1 回答

TA贡献1845条经验 获得超8个赞
当 cgo 系统将你的包装器变成 Go 编译器可以理解的东西时,它必须将每个 C 类型转换为 Go 类型以用于各种目的。事实证明这不适用于您的情况(这是您看到的错误)。
这实际上没关系,因为您的代码一开始就不会按照您想要的方式工作。当 Go 的垃圾收集器准备好释放占用 Go 内存的 Go 对象但返回一个不是C.CstringGo 内存的指针时,运行时终结器就会运行。特别要注意cgo 文档中的以下引用:
// Go string to C string
// The C string is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CString(string) *C.char
由于返回的字符串在“C 堆”上,Go 垃圾收集器永远不会最终确定它。如果您的代码已编译,它将只是一个空操作。
如果你有一个 Go 对象的生命周期与 C 对象的生命周期平行,你也许可以使用它。这是一个虚构的(但有效的)示例:
package main
/*
#include <stdio.h>
#include <stdlib.h>
*/
import "C"
import (
"fmt"
"runtime"
"time"
"unsafe"
)
type S struct {
Foo int
ToFree unsafe.Pointer
}
func main() {
doit()
runtime.GC()
time.Sleep(10 * time.Millisecond) // ugly hack
}
func doit() {
cString := C.CString("Wold!")
fmt.Printf("C.CString type: %T\n", cString)
x := &S{Foo: 1, ToFree: unsafe.Pointer(cString)}
runtime.SetFinalizer(x, func(t *S) {
fmt.Println("freeing C string")
C.free(t.ToFree)
})
}
当分配的对象x超出范围时,它就有资格进行 GC。实际的 GC 可能永远不会发生,所以我强制使用runtime.GC()in 进行main。这会触发终结器:
$ ./cfree_example
C.CString type: *main._Ctype_char
freeing C string
“丑陋的黑客”就在那里,因为如果main在终结器调用完成写入freeing C string消息之前返回,它就会丢失。在一个真正的程序中你不需要这个。
- 1 回答
- 0 关注
- 224 浏览
添加回答
举报