Widac jakis sens

This commit is contained in:
Michał Derkacz
2011-07-01 14:59:27 +02:00
parent bd504423fe
commit b1b421e54b
11 changed files with 555 additions and 105 deletions

View File

@@ -1,7 +1,6 @@
include $(GOROOT)/src/Make.inc
TARG=gobject
CGOFILES=\
gobject.go\
TARG = glib
CGOFILES = pkgconfig.go type.go value.go object.go closure.go signal.go
include $(GOROOT)/src/Make.pkg

88
closure.go Normal file
View File

@@ -0,0 +1,88 @@
package glib
/*
#include "closure.h"
static inline GoClosure* go_closure_ref(GoClosure* c) {
return (GoClosure*) g_closure_ref((GClosure*) c);
}
static inline void go_closure_unref(GoClosure* c) {
g_closure_unref((GClosure*) c);
}
typedef struct {
GClosure *cl;
GValue *ret_val;
guint n_param;
const GValue *params;
gpointer ih;
gpointer data;
} MarshalParams;
extern void go_marshal(gpointer mp);
static void closure_marshal(GClosure* cl, GValue* ret_val, guint n_param,
const GValue* params, gpointer ih, gpointer data) {
MarshalParams mp = {cl, ret_val, n_param, params, ih, data};
go_marshal(&mp);
}
static GoClosure* go_closure_new(void* cb) {
GoClosure *cl = (GoClosure*) g_closure_new_simple(sizeof (GoClosure), NULL);
cl->cb = cb;
g_closure_set_marshal((GClosure *) cl, closure_marshal);
return cl;
}
*/
import "C"
import (
"runtime"
"reflect"
"unsafe"
"fmt"
)
type Closure struct {
cl *C.GoClosure
cb *reflect.Value // Callback function
}
func NewClosure(cb_func interface{}) (c *Closure) {
cb := reflect.ValueOf(cb_func)
if cb.Kind() != reflect.Func {
panic("cb_func is not a function")
}
c = &Closure{C.go_closure_new(unsafe.Pointer(&cb)), &cb}
runtime.SetFinalizer(c, (*Closure).destroy)
return
}
func (c *Closure) Ref() *Closure {
if c.cl == nil {
panic("Ref on nil closure")
}
return &Closure{C.go_closure_ref(c.cl), c.cb}
}
func (c *Closure) Unref() {
if c.cl == nil {
panic("Unref on nil closure")
}
C.go_closure_unref(c.cl)
c.cl = nil
c.cb = nil
}
func (c *Closure) destroy() {
if c.cl != nil {
C.go_closure_unref(c.cl)
}
}
//export go_marshal
func marshal(mp unsafe.Pointer) {
//p := (*C.MarshalParams)(mp)
fmt.Println("Doszedl!")
}

6
closure.h Normal file
View File

@@ -0,0 +1,6 @@
#include <glib-object.h>
typedef struct {
GClosure cl;
gpointer cb;
} GoClosure;

29
glib_test.go Normal file
View File

@@ -0,0 +1,29 @@
package glib
import (
"testing"
)
func TestValue(t *testing.T) {
v1 := uint64(0xdeadbeaf)
a := ValueOf(v1)
b := NewValueInit(TYPE_UINT64)
a.Copy(b)
t.Logf("a = %s(%s), b = %s(%s)", a.Type(), a, b.Type(), b)
if b.Get().(uint64) != v1 {
t.Error("TYPE_UINT64")
}
v2 := -1
a = ValueOf(v2)
b = NewValueInit(TYPE_INT)
a.Copy(b)
t.Logf("a = %s(%s), b = %s(%s)", a.Type(), a, b.Type(), b)
if b.Get() != v2 {
t.Error("TYPE_INT")
}
}
func TestSignal(t *testing.T) {
s := NewSignal("bla", TYPE_NONE, TYPE_GO_INT)
t.Logf("Signal: %s", s)
}

View File

@@ -1,91 +0,0 @@
package glib
/*
#cgo pkg-config: glib-2.0 gobject-2.0
#include <glib-object.h>
*/
import "C"
import (
"runtime"
)
// A numerical value which represents the unique identifier of a registered type
type Type C.GType
const (
TYPE_INVALID = Type(C.G_TYPE_INVALID)
TYPE_NONE = Type(C.G_TYPE_NONE)
TYPE_INTERFACE = Type(C.G_TYPE_INTERFACE)
TYPE_CHAR = Type(C.G_TYPE_CHAR)
TYPE_UCHAR = Type(C.G_TYPE_UCHAR)
TYPE_BOOLEAN = Type(C.G_TYPE_BOOLEAN)
TYPE_INT = Type(C.G_TYPE_INT)
TYPE_UINT = Type(C.G_TYPE_UINT)
TYPE_LONG = Type(C.G_TYPE_LONG)
TYPE_ULONG = Type(C.G_TYPE_ULONG)
TYPE_INT64 = Type(C.G_TYPE_INT64)
TYPE_UINT64 = Type(C.G_TYPE_UINT64)
TYPE_ENUM = Type(C.G_TYPE_ENUM)
TYPE_FLAGS = Type(C.G_TYPE_FLAGS)
TYPE_FLOAT = Type(C.G_TYPE_FLOAT)
TYPE_DOUBLE = Type(C.G_TYPE_DOUBLE)
TYPE_STRING = Type(C.G_TYPE_STRING)
TYPE_POINTER = Type(C.G_TYPE_POINTER)
TYPE_BOXED = Type(C.G_TYPE_BOXED)
TYPE_PARAM = Type(C.G_TYPE_PARAM)
TYPE_OBJECT = Type(C.G_TYPE_OBJECT)
TYPE_VARIANT = Type(C.G_TYPE_VARIANT)
)
var TYPE_GTYPE = Type(C.g_gtype_get_type())
type Object struct {
obj *C.GObject
}
func (o Object) Ref() Object {
if o.obj == nil {
panic("Ref on nil object")
}
return Object{(*C.GObject)(C.g_object_ref(C.gpointer(o.obj)))}
}
func (o Object) Unref() {
if o.obj == nil {
panic("Unref on nil object")
}
C.g_object_unref(C.gpointer(o.obj))
o.obj = nil
}
func (o Object) destroy() {
if o.obj != nil {
C.g_object_unref(C.gpointer(o.obj))
}
}
func MapGObject(obj *C.GObject) (o Object) {
o.obj = obj
runtime.SetFinalizer(o, (*Object).destroy)
return
}
func MapGPointer(p C.gpointer) (o Object) {
return MapGObject((*C.GObject)(p))
}
func NewObject(t Type) Object {
return MapGPointer(C.g_object_newv(C.GType(t), 0, nil))
}
func (o Object) Emit(name string, ...interface{}) {
}
func init() {
C.g_thread_init(nil)
C.g_type_init()
}

View File

@@ -1,11 +0,0 @@
package gobject
import (
"testing"
"time"
)
func TestAll(t *testing.T) {
Print()
time.Sleep(100e9)
}

92
object.go Normal file
View File

@@ -0,0 +1,92 @@
package glib
/*
#include <stdlib.h>
#include "closure.h"
static inline
gulong go_signal_connect(GObject* inst, guint sig, GoClosure* cl) {
return g_signal_connect_closure_by_id(
(gpointer) inst,
sig,
0,
(GClosure*) cl,
TRUE
);
}
static inline
void go_signal_emit(const GValue *inst_and_params, guint sig, GValue *ret) {
return g_signal_emitv(
inst_and_params,
sig,
0,
ret
);
}
*/
import "C"
import (
"runtime"
)
type SigHandlerId C.gulong
type Object struct {
obj *C.GObject
cls map[SigHandlerId]*Closure
}
func (o *Object) Ref() *Object {
if o.obj == nil {
panic("Ref on nil object")
}
return &Object{(*C.GObject)(C.g_object_ref(C.gpointer(o.obj))), o.cls}
}
func (o *Object) Unref() {
if o.obj == nil {
panic("Unref on nil object")
}
C.g_object_unref(C.gpointer(o.obj))
o.obj = nil
o.cls = nil
}
func (o *Object) destroy() {
if o.obj != nil {
C.g_object_unref(C.gpointer(o.obj))
}
}
func MapGObject(obj *C.GObject) (o *Object) {
o = &Object{obj, make(map[SigHandlerId]*Closure)}
runtime.SetFinalizer(o, (*Object).destroy)
return
}
func MapGPointer(p C.gpointer) (o *Object) {
return MapGObject((*C.GObject)(p))
}
func NewObject(t Type) *Object {
return MapGPointer(C.g_object_newv(C.GType(t), 0, nil))
}
func (o *Object) Connect(sig Signal, cb_func interface{}) {
c := NewClosure(cb_func)
h := SigHandlerId(C.go_signal_connect(o.obj, C.guint(sig), c.cl))
o.cls[h] = c
}
func (o *Object) Emit(sig Signal, args ...interface{}) interface{} {
prms := make([]Value, len(args) + 1)
prms[0] = *ValueOf(o.obj)
for i, a := range args {
prms[i+1] = *ValueOf(a)
}
ret := NewValue()
C.go_signal_emit((*C.GValue)(&prms[0]), C.guint(sig), (*C.GValue)(ret))
return ret.Get()
}

4
pkgconfig.go Normal file
View File

@@ -0,0 +1,4 @@
package glib
//#cgo pkg-config: glib-2.0 gobject-2.0
import "C"

42
signal.go Normal file
View File

@@ -0,0 +1,42 @@
package glib
/*
#include <stdlib.h>
#include <glib-object.h>
static inline guint go_signal_new(char* name, GType ot, guint ni, GType* it) {
return g_signal_newv(
name,
G_TYPE_OBJECT,
G_SIGNAL_RUN_LAST,
NULL,
NULL,
NULL,
NULL,
ot,
ni,
it
);
}
*/
import "C"
import (
"unsafe"
)
type Signal C.guint
func NewSignal(name string, ot Type, it ...Type) Signal {
sig_name := C.CString(name)
defer C.free(unsafe.Pointer(sig_name))
var cit *C.GType
if len(it) > 0 {
cit = (*C.GType)(&it[0])
}
return Signal(C.go_signal_new(sig_name, C.GType(ot), C.guint(len(it)), cit))
}
func (s Signal) String() string {
return C.GoString((*C.char)(C.g_signal_name(C.guint(s))))
}

120
type.go Normal file
View File

@@ -0,0 +1,120 @@
package glib
/*
#include <glib-object.h>
#define _GINT_SIZE sizeof(gint)
#define _GLONG_SIZE sizeof(glong)
*/
import "C"
import (
"strconv"
"unsafe"
)
// A numerical value which represents the unique identifier of a registered type
type Type C.GType
const (
TYPE_INVALID = Type(C.G_TYPE_INVALID)
TYPE_NONE = Type(C.G_TYPE_NONE)
TYPE_INTERFACE = Type(C.G_TYPE_INTERFACE)
TYPE_CHAR = Type(C.G_TYPE_CHAR)
TYPE_UCHAR = Type(C.G_TYPE_UCHAR)
TYPE_BOOLEAN = Type(C.G_TYPE_BOOLEAN)
TYPE_INT = Type(C.G_TYPE_INT)
TYPE_UINT = Type(C.G_TYPE_UINT)
TYPE_LONG = Type(C.G_TYPE_LONG)
TYPE_ULONG = Type(C.G_TYPE_ULONG)
TYPE_INT64 = Type(C.G_TYPE_INT64)
TYPE_UINT64 = Type(C.G_TYPE_UINT64)
TYPE_ENUM = Type(C.G_TYPE_ENUM)
TYPE_FLAGS = Type(C.G_TYPE_FLAGS)
TYPE_FLOAT = Type(C.G_TYPE_FLOAT)
TYPE_DOUBLE = Type(C.G_TYPE_DOUBLE)
TYPE_STRING = Type(C.G_TYPE_STRING)
TYPE_POINTER = Type(C.G_TYPE_POINTER)
TYPE_BOXED = Type(C.G_TYPE_BOXED)
TYPE_PARAM = Type(C.G_TYPE_PARAM)
TYPE_OBJECT = Type(C.G_TYPE_OBJECT)
TYPE_VARIANT = Type(C.G_TYPE_VARIANT)
)
var (
TYPE_GTYPE Type
TYPE_GO_INT Type
TYPE_GO_UINT Type
TYPE_GO_INT32 Type
TYPE_GO_UINT32 Type
)
// Returns the Type of the value in the interface{}.
func TypeOf(i interface{}) Type {
switch i.(type) {
case string:
return TYPE_STRING
case int:
return TYPE_GO_INT
case uint:
return TYPE_GO_UINT
case int8:
return TYPE_CHAR
case uint8:
return TYPE_UCHAR
case int32:
return TYPE_GO_INT32
case uint32:
return TYPE_GO_UINT32
case int64:
return TYPE_INT64
case uint64:
return TYPE_UINT64
case bool:
return TYPE_BOOLEAN
case float32:
return TYPE_FLOAT
case float64:
return TYPE_DOUBLE
case unsafe.Pointer:
return TYPE_POINTER
case *Object:
return TYPE_OBJECT
case Type:
return TYPE_GTYPE
}
return TYPE_INVALID
}
func (t Type) String() string {
return C.GoString((*C.char)(C.g_type_name(C.GType(t))))
}
func init() {
C.g_thread_init(nil)
C.g_type_init()
TYPE_GTYPE = Type(C.g_gtype_get_type())
switch strconv.IntSize / 8 {
case uint(C._GINT_SIZE):
TYPE_GO_INT = TYPE_INT
TYPE_GO_UINT = TYPE_UINT
case uint(C._GLONG_SIZE):
TYPE_GO_INT = TYPE_LONG
TYPE_GO_UINT = TYPE_ULONG
case 64:
TYPE_GO_INT = TYPE_INT64
TYPE_GO_UINT = TYPE_UINT64
default:
panic("Unexpectd size of 'int'")
}
switch C.uint(4) {
case C._GINT_SIZE:
TYPE_GO_INT32 = TYPE_INT
TYPE_GO_UINT32 = TYPE_UINT
case C._GLONG_SIZE:
TYPE_GO_INT32 = TYPE_LONG
TYPE_GO_UINT32 = TYPE_ULONG
default:
panic("Neither gint nor glong are 32 bit numbers")
}
}

172
value.go Normal file
View File

@@ -0,0 +1,172 @@
package glib
/*
#include <glib-object.h>
*/
import "C"
import (
"unsafe"
"runtime"
"fmt"
)
// An opaque structure used to hold different types of values.
type Value C.GValue
// Returns v's type.
func (v *Value) Type() Type {
return Type(v.g_type)
}
// Set value to i
func (v *Value) Set(i interface{}) {
switch x := i.(type) {
case string:
C.g_value_set_static_string(
(*C.GValue)(v),
(*C.gchar)(C.CString(x)),
)
case int:
if TYPE_GO_INT == TYPE_INT {
C.g_value_set_int((*C.GValue)(v), C.gint(x))
} else {
C.g_value_set_long((*C.GValue)(v), C.glong(x))
}
case uint:
if TYPE_GO_INT == TYPE_INT {
C.g_value_set_uint((*C.GValue)(v), C.guint(x))
} else {
C.g_value_set_ulong((*C.GValue)(v), C.gulong(x))
}
case int8:
C.g_value_set_char((*C.GValue)(v), C.gchar(x))
case uint8:
C.g_value_set_uchar((*C.GValue)(v), C.guchar(x))
case int32:
if TYPE_GO_INT32 == TYPE_INT {
C.g_value_set_int((*C.GValue)(v), C.gint(x))
} else {
C.g_value_set_long((*C.GValue)(v), C.glong(x))
}
case uint32:
if TYPE_GO_INT32 == TYPE_INT {
C.g_value_set_uint((*C.GValue)(v), C.guint(x))
} else {
C.g_value_set_ulong((*C.GValue)(v), C.gulong(x))
}
case int64:
C.g_value_set_int64((*C.GValue)(v), C.gint64(x))
case uint64:
C.g_value_set_uint64((*C.GValue)(v), C.guint64(x))
case bool:
if x {
C.g_value_set_boolean((*C.GValue)(v), C.gboolean(1))
} else {
C.g_value_set_boolean((*C.GValue)(v), C.gboolean(0))
}
case float32:
C.g_value_set_float((*C.GValue)(v), C.gfloat(x))
case float64:
C.g_value_set_double((*C.GValue)(v), C.gdouble(x))
case unsafe.Pointer:
C.g_value_set_pointer((*C.GValue)(v), C.gpointer(x))
case *Object:
C.g_value_set_object((*C.GValue)(v), C.gpointer(x.obj))
case nil:
C.g_value_reset((*C.GValue)(v))
default:
panic("Unknown type")
}
}
// Returns new uninitialized value
func NewValue() *Value {
v := new(Value)
runtime.SetFinalizer(v, (*Value).Unset)
return v
}
// Initializes value with the default value of type.
func (v *Value) Init(t Type) {
C.g_value_init((*C.GValue)(v), C.GType(t))
}
// Clears the current value in value and "unsets" the type,
func (v *Value) Unset() {
C.g_value_unset((*C.GValue)(v))
}
// Returns new initializes value
func NewValueInit(t Type) *Value {
v := NewValue()
v.Init(t)
return v
}
// Returns a new Value initialized to the value stored in the interface i.
func ValueOf(i interface{}) *Value {
v := NewValueInit(TypeOf(i))
v.Set(i)
return v
}
// Copies the value into dst.
func (v *Value) Copy(dst *Value) {
C.g_value_copy((*C.GValue)(v), (*C.GValue)(dst))
}
func (v *Value) Get() interface{} {
switch Type((*C.GValue)(v).g_type) {
case TYPE_STRING:
return C.GoString((*C.char)(C.g_value_get_string((*C.GValue)(v))))
case TYPE_GO_INT:
if TYPE_GO_INT == TYPE_INT {
return int(C.g_value_get_int((*C.GValue)(v)))
} else {
return int(C.g_value_get_long((*C.GValue)(v)))
}
case TYPE_GO_UINT:
if TYPE_GO_INT == TYPE_INT {
return uint(C.g_value_get_uint((*C.GValue)(v)))
} else {
return uint(C.g_value_get_ulong((*C.GValue)(v)))
}
case TYPE_CHAR:
return int8(C.g_value_get_char((*C.GValue)(v)))
case TYPE_UCHAR:
return uint8(C.g_value_get_uchar((*C.GValue)(v)))
case TYPE_GO_INT32:
if TYPE_GO_INT32 == TYPE_INT {
return int32(C.g_value_get_int((*C.GValue)(v)))
} else {
return int32(C.g_value_get_long((*C.GValue)(v)))
}
case TYPE_GO_UINT32:
if TYPE_GO_INT32 == TYPE_INT {
return uint32(C.g_value_get_uint((*C.GValue)(v)))
} else {
return uint32(C.g_value_get_ulong((*C.GValue)(v)))
}
case TYPE_INT64:
return int64(C.g_value_get_int64((*C.GValue)(v)))
case TYPE_UINT64:
return uint64(C.g_value_get_uint64((*C.GValue)(v)))
case TYPE_BOOLEAN:
return (C.g_value_get_boolean((*C.GValue)(v)) != C.gboolean(0))
case TYPE_FLOAT:
return float32(C.g_value_get_float((*C.GValue)(v)))
case TYPE_DOUBLE:
return float64(C.g_value_get_double((*C.GValue)(v)))
case TYPE_POINTER:
return unsafe.Pointer(C.g_value_get_pointer((*C.GValue)(v)))
case TYPE_OBJECT:
return MapGPointer(C.g_value_get_object((*C.GValue)(v)))
}
// TODO - shoulda work with more GLIB types
panic("Can't represent value in Go type system.")
}
func (v *Value) String() string {
return fmt.Sprint(v.Get())
}