3

我正在包装一个 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))
}

这是行不通的,而且显然是错误的方法。

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

4

2 回答 2

3

如果您获取 an 的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)
}
于 2013-03-11T13:35:54.377 回答
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
于 2013-12-28T14:26:33.973 回答