我正在包装一个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 *数据,但是这个无长度的接口使我无法接受。
答案 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