2013-03-11 3 views
3

임의로 데이터를 보유하는 데 사용할 수있는 void * 데이터 필드가있는 구조체가있는 C 라이브러리를 래핑하고 있습니다. 이것이 관용적 인 Go에서 이것을 감싸는 최선의 방법은 무엇입니까 (심지어 가능하다면)? 내가 좋아하는 뭔가를 할 기대했다Golang (cgo) - Arbitrary void * interface

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

- https://github.com/boj/goenet - 여전히 있지만 약간의 버그를, 그래서 조심해. – bojo

답변

2

내 벨트 아래로 이동 몇 개월 이상 후이 다시오고 내가 와서 다음 (업데이트, 감사 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 
+0

왜 데이터를'& FooData {}'에 저장해야합니까? – zupa

+0

나는 한동안 ENet 라이브러리를 포장했다. 데이터 필드에 아무 것도 저장할 필요는 없지만 클라이언트 라이브러리가 피어를 플레이어 (예 : http://enet.bespin.org/structENetPeer)와 같은 인 - 게임 구성에 연결하는 메커니즘으로 사용됩니다. html # a1873959810db7ac7a02da90469ee384e – bojo

+0

죄송합니다. 제 질문에 명확하지 않았습니다. 왜 데이터를 저장해야하는지 묻지 않습니다. 'f.data = unsafe.Pointer (& data)'를 직접 사용하는 대신'& FooData {}'에'data '를 왜 포장하는지 묻습니다. – zupa

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) 
} 
+0

네, 제 질문을 게시 한 이래로 제가 생각해 봤습니다. – bojo

+1

'reflect.Elem()'과'reflect.Pointer()'를 사용하여 인터페이스의 포함 된 값에'uintptr'을 얻을 수도 있습니다. – thwd

+0

[reflect.func (Value) Pointer] (http://golang.org/pkg/reflect/#Value.Pointer) : _ v 종류가 Chan, Func, Map, Ptr, Slice 또는 UnsafePointer가 아닌 경우 패닉이 발생합니다. . "_ – zzzz