func registerType(spec *TypeSpec, singleton bool) 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) 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)) types = append(types, &localSpec) }) // TODO Are there really no errors possible from qmlRegisterType? return err }
func registerType(spec *TypeSpec, singleton bool) 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) cres := C.int(0) if singleton { cres = C.registerSingleton(cloc, C.int(localSpec.Major), C.int(localSpec.Minor), cname, typeInfo(sample), unsafe.Pointer(&localSpec)) } else { cres = C.registerType(cloc, C.int(localSpec.Major), C.int(localSpec.Minor), cname, typeInfo(sample), unsafe.Pointer(&localSpec)) } // It doesn't look like it keeps references to these, but it's undocumented and unclear. C.free(unsafe.Pointer(cloc)) C.free(unsafe.Pointer(cname)) if cres == -1 { err = fmt.Errorf("QML engine failed to register type; invalid type location or name?") } else { types = append(types, &localSpec) } }) return err }
func registerType(location string, major, minor int, spec *TypeSpec) error { // Copy and hold a reference to the spec data. localSpec := *spec f := reflect.ValueOf(localSpec.Init) ft := f.Type() if ft.Kind() != reflect.Func { return fmt.Errorf("TypeSpec.Init must be a function, got %#v", localSpec.Init) } if ft.NumIn() != 1 { return fmt.Errorf("TypeSpec.Init's function must accept single argument: %s", ft) } // firstArg := ft.In(0) // if firstArg.Kind() != reflect.Ptr || firstArg.Elem().Kind() == reflect.Ptr { // return fmt.Errorf("TypeSpec.Init's function must take a pointer type as the first argument: %s", ft) // } if ft.In(0) != typeObject { return fmt.Errorf("TypeSpec.Init's function must take qml.Object as the second argument: %s", ft) } if ft.NumOut() != 1 { return fmt.Errorf("TypeSpec.Init's function must return instance pointer: %s", ft) } returnValue := ft.Out(0) if returnValue.Kind() != reflect.Ptr { return fmt.Errorf("TypeSpec.Init's function must return a pointer type: %s", ft) } customType := typeInfo(reflect.New(returnValue.Elem()).Interface()) if localSpec.Name == "" { localSpec.Name = returnValue.Elem().Name() if localSpec.Name == "" { panic("cannot determine registered type name; please provide one explicitly") } } var err error RunMain(func() { cloc := C.CString(location) cname := C.CString(localSpec.Name) cres := C.int(0) if localSpec.Singleton { cres = C.registerSingleton(cloc, C.int(major), C.int(minor), cname, customType, unsafe.Pointer(&localSpec)) } else { cres = C.registerType(cloc, C.int(major), C.int(minor), cname, customType, unsafe.Pointer(&localSpec)) } // It doesn't look like it keeps references to these, but it's undocumented and unclear. C.free(unsafe.Pointer(cloc)) C.free(unsafe.Pointer(cname)) if cres == -1 { err = fmt.Errorf("QML engine failed to register type; invalid type location or name?") } else { types = append(types, &localSpec) } }) return err }