Golang(cgo) - 任意无效*界面

时间:2013-03-11 13:16:46

标签: go cgo

我正在包装一个C库,该库具有一个带有void *数据字段的结构,可用于任意保存数据。什么是最好的方式(如果它甚至可能)将其包装在惯用的Go?

结构非常简单:

typedef struct _Foo {
    void * data;
} Foo;

我希望做类似的事情:

type Foo C.Foo

func (f *Foo) SetData(data interface{}) {
    f.data = unsafe.Pointer(&data)
}

func (f *Foo) Data() interface{} {
    return (interface{})(unsafe.Pointer(f.data))
}

这不起作用,反正显然是错误的做法。

我已经使用[]字节源成功设置了一个带有长度字段的void *数据,但是这个无长度的接口使我无法接受。

2 个答案:

答案 0 :(得分:3)

如果您采用interface的地址,则会获取值类型的地址(大致为struct { tInfo *typeInfo, payload uintPtr}),而不是接口的“装箱”数据。如果有效载荷字段适合于机械词,则有效载荷字段可以保存实际数据,否则该字段保存指向实际有效载荷的指针。但这些是实施细节,不应直接与IMO合作。

我会非常规,如(未经测试的代码,仅架构):

func (f *Foo) SetT(p *T) {
        (*C.Foo)(f).data = unsafe.Pointer(p)
}

func (f *Foo) GetT() *T {
        return (*T)((*C.Foo)(f).data)
}

答案 1 :(得分:2)

经过几个月的Go后回到这里,我想出了以下(更新,谢谢zupa)解决方案。

func (f *Foo) SetData(data interface{}) {
    f.data = unsafe.Pointer(&data)
}

func (f *Foo) Data() interface{} {
    return unsafe.Pointer(f.data)
}

可以按以下方式使用:

type Player struct {
    Name string
}

p := &Player{
    Name: "Player1",
}

f.SetData(p)

log.Print(f.Data().(*Player).Name) // Outputs: Player1