Skip to content

Commit

Permalink
Some de-duplication.
Browse files Browse the repository at this point in the history
  • Loading branch information
niemeyer committed Sep 5, 2013
1 parent 5417c02 commit 6573692
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 63 deletions.
52 changes: 16 additions & 36 deletions bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,31 +193,9 @@ func hookGoValueDestroyed(enginep unsafe.Pointer, foldp unsafe.Pointer) {

//export hookGoValueReadField
func hookGoValueReadField(enginep unsafe.Pointer, foldp unsafe.Pointer, memberIndex C.int, result *C.DataValue) {
field := foldField(enginep, foldp, memberIndex)
fold := (*valueFold)(foldp)

if fold.engine == nil {
if enginep == nilPtr {
panic("reading field from value without an engine pointer; who created the value?")
}
engine := engines[enginep]
if engine == nil {
panic("unknown engine pointer; who created the engine?")
}
fold.engine = engine
engine.values[fold.gvalue] = fold
before := len(enginePending)
delete(enginePending, fold)
if len(enginePending) == before {
panic("value had no engine, but is not in the pending engine set; who created the value?")
}
}

v := reflect.ValueOf(fold.gvalue)
for v.Type().Kind() == reflect.Ptr {
v = v.Elem()
}
field := v.Field(int(memberIndex))

// TODO Strings are being passed in an unsafe manner here. There is a
// small chance that the field is changed and the garbage collector is run
// before C++ has a chance to look at the data. We can solve this problem
Expand All @@ -228,11 +206,24 @@ func hookGoValueReadField(enginep unsafe.Pointer, foldp unsafe.Pointer, memberIn

//export hookGoValueWriteField
func hookGoValueWriteField(enginep unsafe.Pointer, foldp unsafe.Pointer, memberIndex C.int, dvalue *C.DataValue) {
field := foldField(enginep, foldp, memberIndex)
value := unpackDataValue(dvalue)

// TODO What to do if it fails?
convertAndSet(field, reflect.ValueOf(value))
}

func convertAndSet(to, from reflect.Value) {
// TODO Catch the panic and error out.
to.Set(from.Convert(to.Type()))
}

func foldField(enginep unsafe.Pointer, foldp unsafe.Pointer, memberIndex C.int) reflect.Value {
fold := (*valueFold)(foldp)

if fold.engine == nil {
if enginep == nilPtr {
panic("reading field from value without an engine pointer; who created the value?")
panic("accessing field from value without an engine pointer; who created the value?")
}
engine := engines[enginep]
if engine == nil {
Expand All @@ -251,17 +242,6 @@ func hookGoValueWriteField(enginep unsafe.Pointer, foldp unsafe.Pointer, memberI
for v.Type().Kind() == reflect.Ptr {
v = v.Elem()
}
field := v.Field(int(memberIndex))

// TODO Put the above in a function and share with Read.

value := unpackDataValue(dvalue)

// TODO What to do if it fails?
convertAndSet(field, reflect.ValueOf(value))
return v.Field(int(memberIndex))
}

func convertAndSet(to, from reflect.Value) {
// TODO Catch the panic and error out.
to.Set(from.Convert(to.Type()))
}
37 changes: 10 additions & 27 deletions qml.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,35 +364,14 @@ type TypeSpec struct {
var types []*TypeSpec

func RegisterType(spec *TypeSpec) error {
// Copy and hold a reference to the spec data.
localSpec := *spec

// TODO Validate localSpec fields.

var err error
gui(func() {
sample := spec.New()
if sample == nil {
err = fmt.Errorf("TypeSpec.New for type %q returned nil", spec.Name)
return
}

cloc := C.CString(localSpec.Location)
cname := C.CString(localSpec.Name)
C.registerType(cloc, C.int(localSpec.Major), C.int(localSpec.Minor), cname, typeInfo(sample), unsafe.Pointer(&localSpec))
// TODO Check if qmlRegisterType keeps a reference to those.
//C.free(unsafe.Pointer(cloc))
//C.free(unsafe.Pointer(cname))
types = append(types, &localSpec)
})

// TODO Are there really no errors possible from qmlRegisterType?
return err
return registerType(spec, false)
}

// TODO Put logic in RegisterType and RegisterSingle in a single internal function.

func RegisterSingleton(spec *TypeSpec) error {
return registerType(spec, true)
}

func registerType(spec *TypeSpec, singleton bool) error {
// Copy and hold a reference to the spec data.
localSpec := *spec

Expand All @@ -408,7 +387,11 @@ func RegisterSingleton(spec *TypeSpec) error {

cloc := C.CString(localSpec.Location)
cname := C.CString(localSpec.Name)
C.registerSingleton(cloc, C.int(localSpec.Major), C.int(localSpec.Minor), cname, typeInfo(sample), unsafe.Pointer(&localSpec))
if singleton {
C.registerSingleton(cloc, C.int(localSpec.Major), C.int(localSpec.Minor), cname, typeInfo(sample), unsafe.Pointer(&localSpec))
} else {
C.registerType(cloc, C.int(localSpec.Major), C.int(localSpec.Minor), cname, typeInfo(sample), unsafe.Pointer(&localSpec))
}
// TODO Check if qmlRegisterType keeps a reference to those.
//C.free(unsafe.Pointer(cloc))
//C.free(unsafe.Pointer(cname))
Expand Down

0 comments on commit 6573692

Please sign in to comment.