From 0cf1eb3930488318a7d23505c25900442230023a Mon Sep 17 00:00:00 2001 From: Roland Singer Date: Mon, 14 Jan 2019 23:15:20 +0100 Subject: [PATCH] further progress --- TODO.md | 11 +- app.go | 99 +++++++++++++---- error.go | 68 ++++++++++++ errors.go | 83 ++++++++++++++ gml.go | 14 +++ image.go | 17 ++- internal/binding/headers/gml.h | 1 + internal/binding/headers/gml_app.h | 17 +-- internal/binding/headers/gml_error.h | 7 +- internal/binding/headers/gml_image.h | 2 +- internal/binding/sources/gml_app.cpp | 92 +++++++-------- internal/binding/sources/gml_app.h | 1 + internal/binding/sources/gml_error.cpp | 105 ++++++++++++++++++ internal/binding/sources/gml_error.h | 10 +- internal/binding/sources/gml_image.cpp | 17 +-- .../binding/sources/gml_imageprovider.cpp | 14 +-- internal/binding/sources/gml_includes.h | 2 + internal/binding/sources/gml_variant.cpp | 65 +++++------ internal/build/qtproject.go | 2 +- internal/build/resources.go | 2 +- samples/hello_world/main.go | 3 +- samples/signals_slots/main.go | 3 +- 22 files changed, 487 insertions(+), 148 deletions(-) create mode 100644 error.go create mode 100644 errors.go create mode 100644 internal/binding/sources/gml_error.cpp diff --git a/TODO.md b/TODO.md index 81d36d6..386c600 100644 --- a/TODO.md +++ b/TODO.md @@ -1,9 +1,10 @@ # TODO -- finish verbose mode - set core.QCoreApplication_SetApplicationName("App") core.QCoreApplication_SetOrganizationName("Desertbit") -- ImageProvider -- signals & slots +- slots return values - docker container -- call qml slots directly from go +- properties +- models - dp for pixels -- document, that slot names must not overlap with QObject names! \ No newline at end of file +- add catch exception also to free methods. +- document, that slot names must not overlap with QObject names! +- call qml slots directly from go? diff --git a/app.go b/app.go index ff7c3bd..5bceef3 100644 --- a/app.go +++ b/app.go @@ -52,13 +52,13 @@ func init() { C.gml_app_init() } -// TODO: free type App struct { + freed bool threadID int app C.gml_app argc int - argv **C.char // TODO: free + argv **C.char mutex sync.Mutex ctxPropMap map[string]interface{} @@ -78,6 +78,9 @@ func NewAppWithArgs(args []string) (a *App, err error) { // Ensure the thread is locked within this context of app creation. runtime.LockOSThread() + apiErr := errorPool.Get() + defer errorPool.Put(apiErr) + a = &App{ threadID: utils.GetThreadID(), argc: len(args), @@ -85,10 +88,31 @@ func NewAppWithArgs(args []string) (a *App, err error) { ctxPropMap: make(map[string]interface{}), imgProvMap: make(map[string]*ImageProvider), } - a.app = C.gml_app_new(C.int(a.argc), a.argv) + + a.app = C.gml_app_new(C.int(a.argc), a.argv, apiErr.err) + if a.app == nil { + err = apiErr.Err("failed to create new app") + return + } + + // Always free the C value. + runtime.SetFinalizer(a, freeApp) return } +func freeApp(a *App) { + if a.freed { + return + } + a.freed = true + C.gml_app_free(a.app) + freeCharArray(a.argv, a.argc) +} + +func (a *App) Free() { + freeApp(a) +} + // RunMain runs the function on the applications main thread. func (a *App) RunMain(f func()) { // Check if already running on the main thread. @@ -106,11 +130,10 @@ func (a *App) RunMain(f func()) { ptr := pointer.Save(cb) defer pointer.Unref(ptr) - // TODO: - _ = C.gml_app_run_main(a.app, ptr) - /*if error { + ret := C.gml_app_run_main(a.app, ptr) + if ret != 0 { return - }*/ + } <-doneChan } @@ -121,31 +144,39 @@ func (a *App) Load(url string) error { urlC := C.CString(url) defer C.free(unsafe.Pointer(urlC)) - // TODO: - _ = int(C.gml_app_load(a.app, urlC)) + apiErr := errorPool.Get() + defer errorPool.Put(apiErr) + + ret := C.gml_app_load(a.app, urlC, apiErr.err) + if ret != 0 { + return apiErr.Err("failed to load url") + } return nil } -// Load the QML given in data. +// LoadData loads the QML given in data. // Hint: Must be called within main thread. func (a *App) LoadData(data string) error { dataC := C.CString(data) defer C.free(unsafe.Pointer(dataC)) - // TODO: - _ = int(C.gml_app_load_data(a.app, dataC)) + apiErr := errorPool.Get() + defer errorPool.Put(apiErr) + + ret := C.gml_app_load_data(a.app, dataC, apiErr.err) + if ret != 0 { + return apiErr.Err("failed to load data") + } return nil } // AddImportPath adds the given import path to the app engine. // Hint: Must be called within main thread. -func (a *App) AddImportPath(path string) error { +func (a *App) AddImportPath(path string) { pathC := C.CString(path) defer C.free(unsafe.Pointer(pathC)) - // TODO: - _ = int(C.gml_app_add_import_path(a.app, pathC)) - return nil + C.gml_app_add_import_path(a.app, pathC) } // AddImageProvider adds the image provider to the app engine for the given id. @@ -153,9 +184,16 @@ func (a *App) AddImageProvider(id string, ip *ImageProvider) error { idC := C.CString(id) defer C.free(unsafe.Pointer(idC)) + apiErr := errorPool.Get() + defer errorPool.Put(apiErr) + + var ret C.int a.RunMain(func() { - _ = int(C.gml_app_add_imageprovider(a.app, idC, ip.ip)) + ret = C.gml_app_add_imageprovider(a.app, idC, ip.ip, apiErr.err) }) + if ret != 0 { + return apiErr.Err("failed to add image provider") + } // Add to map to ensure it gets not garbage collected. // It is in use by the C++ context; @@ -169,16 +207,23 @@ func (a *App) AddImageProvider(id string, ip *ImageProvider) error { // Exec executes the application and returns the exit code. // This method is blocking. // Hint: Must be called within main thread. -func (a *App) Exec() int { - return int(C.gml_app_exec(a.app)) +func (a *App) Exec() (retCode int, err error) { + apiErr := errorPool.Get() + defer errorPool.Put(apiErr) + + retCode = int(C.gml_app_exec(a.app, apiErr.err)) + if retCode != 0 { + err = apiErr.Err("app execution failed") + return + } + return } // Quit the application. -func (a *App) Quit() (retCode int) { +func (a *App) Quit() { a.RunMain(func() { - retCode = int(C.gml_app_quit(a.app)) + C.gml_app_quit(a.app) }) - return } func (a *App) SetContextProperty(name string, v interface{}) (err error) { @@ -195,10 +240,16 @@ func (a *App) SetContextProperty(name string, v interface{}) (err error) { nameC := C.CString(name) defer C.free(unsafe.Pointer(nameC)) + apiErr := errorPool.Get() + defer errorPool.Put(apiErr) + + var ret C.int a.RunMain(func() { - // TODO: - _ = int(C.gml_app_set_root_context_property(a.app, nameC, obj.cObject())) + ret = C.gml_app_set_root_context_property(a.app, nameC, obj.cObject(), apiErr.err) }) + if ret != 0 { + return apiErr.Err("failed to set context property") + } // Add to map to ensure it gets not garbage collected. // It is in use by the C++ context; diff --git a/error.go b/error.go new file mode 100644 index 0000000..c1cabc0 --- /dev/null +++ b/error.go @@ -0,0 +1,68 @@ +/* + * GML - Go QML + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Roland Singer + * Copyright (c) 2019 Sebastian Borchers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package gml + +// #include +import "C" +import "errors" + +type apiError struct { + err C.gml_error +} + +func newAPIError() *apiError { + return &apiError{ + err: C.gml_error_new(), + } +} + +func (e *apiError) Free() { + C.gml_error_free(e.err) +} + +func (e *apiError) String() string { + return C.GoString(C.gml_error_get_msg(e.err)) +} + +func (e *apiError) Reset() { + C.gml_error_reset(e.err) +} + +func (e *apiError) Err(prefix ...string) error { + s := e.String() + if len(prefix) > 0 { + if len(s) == 0 { + s = prefix[0] + } else { + s = prefix[0] + ": " + s + } + } else if len(s) == 0 { + s = "unknown error" + } + return errors.New(s) +} diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..f82e352 --- /dev/null +++ b/errors.go @@ -0,0 +1,83 @@ +/* + * GML - Go QML + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Roland Singer + * Copyright (c) 2019 Sebastian Borchers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package gml + +const ( + errorPoolSize = 50 +) + +var ( + errorPool = newAPIErrorPool(errorPoolSize) +) + +type apiErrorPool struct { + pool chan *apiError +} + +func newAPIErrorPool(poolSize int) *apiErrorPool { + return &apiErrorPool{ + pool: make(chan *apiError, poolSize), + } +} + +// Get an error from the pool. +// Allocates new memory if the pool is empty. +func (p *apiErrorPool) Get() (e *apiError) { + select { + case e = <-p.pool: + default: + e = newAPIError() + } + return +} + +// Put an error back to the pool. +func (p *apiErrorPool) Put(e *apiError) { + // Reset the error message. + e.Reset() + + select { + case p.pool <- e: + default: + // Just let it go. The pool is full. + e.Free() + } +} + +// Reset empties the pool. +func (p *apiErrorPool) Reset() { + var e *apiError + for { + select { + case e = <-p.pool: + e.Free() + default: + return + } + } +} diff --git a/gml.go b/gml.go index 87cf227..4ca431d 100644 --- a/gml.go +++ b/gml.go @@ -32,3 +32,17 @@ package gml // #cgo LDFLAGS: -lstdc++ // #include import "C" +import ( + "fmt" + "os" +) + +// Exec executes the app, prints errors and exits +// the application with the specific exit code. +func Exec(a *App) { + ret, err := a.Exec() + if err != nil { + fmt.Println(err) + } + os.Exit(ret) +} diff --git a/image.go b/image.go index 35f0328..3b4e534 100644 --- a/image.go +++ b/image.go @@ -78,8 +78,17 @@ func (img *Image) Free() { freeImage(img) } -func (img *Image) LoadFromData(data []byte) (err error) { - // TODO: - _ = C.gml_image_load_from_data(img.img, (*C.char)(unsafe.Pointer(&data[0])), C.int(len(data))) - return +func (img *Image) LoadFromData(data []byte) error { + if len(data) == 0 { + return fmt.Errorf("empty data") + } + + apiErr := errorPool.Get() + defer errorPool.Put(apiErr) + + ret := C.gml_image_load_from_data(img.img, (*C.char)(unsafe.Pointer(&data[0])), C.int(len(data)), apiErr.err) + if ret != 0 { + return apiErr.Err("failed to load from data") + } + return nil } diff --git a/internal/binding/headers/gml.h b/internal/binding/headers/gml.h index 3c88bc3..591dc3e 100644 --- a/internal/binding/headers/gml.h +++ b/internal/binding/headers/gml.h @@ -31,6 +31,7 @@ #include #include +#include "gml_error.h" #include "gml_app.h" #include "gml_image.h" #include "gml_object.h" diff --git a/internal/binding/headers/gml_app.h b/internal/binding/headers/gml_app.h index 5cc6f04..a2c4039 100644 --- a/internal/binding/headers/gml_app.h +++ b/internal/binding/headers/gml_app.h @@ -32,6 +32,7 @@ extern "C" { #endif +#include "gml_error.h" #include "gml_object.h" #include "gml_imageprovider.h" @@ -40,18 +41,18 @@ typedef void* gml_app; typedef void (*gml_app_run_main_cb_t)(void* go_ptr); void gml_app_run_main_cb_register(gml_app_run_main_cb_t cb); -gml_app gml_app_new (int argv, char** argc); +gml_app gml_app_new (int argv, char** argc, gml_error err); void gml_app_free(gml_app app); -int gml_app_exec(gml_app app); -int gml_app_quit(gml_app app); +int gml_app_exec(gml_app app, gml_error err); +void gml_app_quit(gml_app app); int gml_app_run_main(gml_app app, void* go_ptr); -int gml_app_load (gml_app app, const char* url); -int gml_app_load_data(gml_app app, const char* data); -int gml_app_add_import_path(gml_app app, const char* path); -int gml_app_add_imageprovider(gml_app app, const char* id, gml_imageprovider ip); +int gml_app_load (gml_app app, const char* url, gml_error err); +int gml_app_load_data(gml_app app, const char* data, gml_error err); +void gml_app_add_import_path(gml_app app, const char* path); +int gml_app_add_imageprovider(gml_app app, const char* id, gml_imageprovider ip, gml_error err); -int gml_app_set_root_context_property(gml_app app, const char* name, gml_object obj); +int gml_app_set_root_context_property(gml_app app, const char* name, gml_object obj, gml_error err); #ifdef __cplusplus } diff --git a/internal/binding/headers/gml_error.h b/internal/binding/headers/gml_error.h index 33cb956..97d3952 100644 --- a/internal/binding/headers/gml_error.h +++ b/internal/binding/headers/gml_error.h @@ -32,7 +32,12 @@ extern "C" { #endif -typedef void* gml_object; +typedef void* gml_error; + +gml_error gml_error_new(); +void gml_error_free (gml_error err); +void gml_error_reset (gml_error err); +const char* gml_error_get_msg(gml_error err); #ifdef __cplusplus } diff --git a/internal/binding/headers/gml_image.h b/internal/binding/headers/gml_image.h index 4eed69a..32f3a3d 100644 --- a/internal/binding/headers/gml_image.h +++ b/internal/binding/headers/gml_image.h @@ -36,7 +36,7 @@ typedef void* gml_image; gml_image gml_image_new(); void gml_image_free(gml_image img); -int gml_image_load_from_data(gml_image img, char* data, int size); +int gml_image_load_from_data(gml_image img, char* data, int size, gml_error err); #ifdef __cplusplus } diff --git a/internal/binding/sources/gml_app.cpp b/internal/binding/sources/gml_app.cpp index fa6a705..555e1f7 100644 --- a/internal/binding/sources/gml_app.cpp +++ b/internal/binding/sources/gml_app.cpp @@ -41,17 +41,17 @@ void gml_app_run_main_cb_register(gml_app_run_main_cb_t cb) { gml_app_run_main_cb = cb; } -gml_app gml_app_new(int argc, char** argv) { +gml_app gml_app_new(int argc, char** argv, gml_error err) { try { GmlApp* a = new GmlApp(argc, argv); return (void*)a; } catch (std::exception& e) { - //api_error_set_msg(err, e.what()); TODO: + gml_error_set_msg(err, e.what()); return NULL; } catch (...) { - //api_error_set_unknown_msg(err); TODO: + gml_error_set_catched_exception_msg(err); return NULL; } } @@ -65,34 +65,31 @@ void gml_app_free(gml_app app) { app = NULL; } -int gml_app_exec(gml_app app) { +int gml_app_exec(gml_app app, gml_error err) { try { GmlApp* a = (GmlApp*)app; return a->app.exec(); } catch (std::exception& e) { - //api_error_set_msg(err, e.what()); TODO: - return -1; // TODO: + gml_error_set_msg(err, e.what()); + return -1; } catch (...) { - //api_error_set_unknown_msg(err); TODO: - return -1; // TODO: + gml_error_set_catched_exception_msg(err); + return -1; } } -int gml_app_quit(gml_app app) { +void gml_app_quit(gml_app app) { try { GmlApp* a = (GmlApp*)app; a->app.quit(); - return 0; // TODO: } catch (std::exception& e) { - //api_error_set_msg(err, e.what()); TODO: - return -1; // TODO: + gml_error_log_exception(e.what()); } catch (...) { - //api_error_set_unknown_msg(err); TODO: - return -1; // TODO: + gml_error_log_exception(); } } @@ -100,97 +97,94 @@ int gml_app_run_main(gml_app app, void* go_ptr) { try { GmlApp* a = (GmlApp*)app; emit a->requestRunMain(go_ptr); - return 0; // TODO: + return 0; } catch (std::exception& e) { - //api_error_set_msg(err, e.what()); TODO: - return -1; // TODO: + gml_error_log_exception(e.what()); + return -1; } catch (...) { - //api_error_set_unknown_msg(err); TODO: - return -1; // TODO: + gml_error_log_exception(); + return -1; } } -int gml_app_load(gml_app app, const char* url) { +int gml_app_load(gml_app app, const char* url, gml_error err) { try { GmlApp* a = (GmlApp*)app; a->engine.load(QUrl(url)); - return 0; // TODO: + return 0; } catch (std::exception& e) { - //api_error_set_msg(err, e.what()); TODO: - return -1; // TODO: + gml_error_set_msg(err, e.what()); + return -1; } catch (...) { - //api_error_set_unknown_msg(err); TODO: - return -1; // TODO: + gml_error_set_catched_exception_msg(err); + return -1; } } -int gml_app_load_data(gml_app app, const char* data) { +int gml_app_load_data(gml_app app, const char* data, gml_error err) { try { GmlApp* a = (GmlApp*)app; a->engine.loadData(data); - return 0; // TODO: + return 0; } catch (std::exception& e) { - //api_error_set_msg(err, e.what()); TODO: - return -1; // TODO: + gml_error_set_msg(err, e.what()); + return -1; } catch (...) { - //api_error_set_unknown_msg(err); TODO: - return -1; // TODO: + gml_error_set_catched_exception_msg(err); + return -1; } } -int gml_app_add_import_path(gml_app app, const char* path) { +void gml_app_add_import_path(gml_app app, const char* path) { try { GmlApp* a = (GmlApp*)app; a->engine.addImportPath(path); - return 0; // TODO: } catch (std::exception& e) { - //api_error_set_msg(err, e.what()); TODO: - return -1; // TODO: + gml_error_log_exception(e.what()); } catch (...) { - //api_error_set_unknown_msg(err); TODO: - return -1; // TODO: + gml_error_log_exception(); } } -int gml_app_add_imageprovider(gml_app app, const char* id, gml_imageprovider ip) { +int gml_app_add_imageprovider(gml_app app, const char* id, gml_imageprovider ip, gml_error err) { try { GmlApp* a = (GmlApp*)app; GmlImageProvider* gip = (GmlImageProvider*)ip; a->engine.addImageProvider(id, gip); - return 0; // TODO: + return 0; } catch (std::exception& e) { - //api_error_set_msg(err, e.what()); TODO: - return -1; // TODO: + gml_error_set_msg(err, e.what()); + return -1; } catch (...) { - //api_error_set_unknown_msg(err); TODO: - return -1; // TODO: + gml_error_set_catched_exception_msg(err); + return -1; } } -int gml_app_set_root_context_property(gml_app app, const char* name, gml_object obj) { +int gml_app_set_root_context_property(gml_app app, const char* name, gml_object obj, gml_error err) { try { GmlApp* a = (GmlApp*)app; QObject* o = (QObject*)obj; a->engine.rootContext()->setContextProperty(name, o); - return 0; // TODO: + return 0; } catch (std::exception& e) { - //api_error_set_msg(err, e.what()); TODO: - return -1; // TODO: + gml_error_set_msg(err, e.what()); + return -1; } catch (...) { - //api_error_set_unknown_msg(err); TODO: - return -1; // TODO: + gml_error_set_catched_exception_msg(err); + return -1; } } diff --git a/internal/binding/sources/gml_app.h b/internal/binding/sources/gml_app.h index 962be64..0bcc98b 100644 --- a/internal/binding/sources/gml_app.h +++ b/internal/binding/sources/gml_app.h @@ -29,6 +29,7 @@ #define GML_APP_H #include "gml_includes.h" +#include "gml_error.h" #include "gml_imageprovider.h" class GmlApp : public QObject diff --git a/internal/binding/sources/gml_error.cpp b/internal/binding/sources/gml_error.cpp new file mode 100644 index 0000000..e934880 --- /dev/null +++ b/internal/binding/sources/gml_error.cpp @@ -0,0 +1,105 @@ +/* + * GML - Go QML + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Roland Singer + * Copyright (c) 2019 Sebastian Borchers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "gml_error.h" + +//#############// +//### C API ###// +//#############// + +gml_error gml_error_new() { + try { + GmlError* gerr = new GmlError(); + return (void*)gerr; + } + catch (std::exception& e) { + gml_error_log_exception("new gml_error: " + string(e.what())); + return NULL; + } + catch (...) { + gml_error_log_exception("new gml_error"); + return NULL; + } +} + +void gml_error_free(gml_error err) { + if (err == NULL) { + return; + } + GmlError* gerr = (GmlError*)err; + delete gerr; + err = NULL; +} + +void gml_error_reset(gml_error err) { + try { + GmlError* gerr = (GmlError*)err; + gerr->msg = ""; + } + catch (std::exception& e) { + gml_error_log_exception("reset error message: " + string(e.what())); + } + catch (...) { + gml_error_log_exception("reset error message"); + } +} + +const char* gml_error_get_msg(gml_error err) { + try { + GmlError* gerr = (GmlError*)err; + return gerr->msg.c_str(); + } + catch (std::exception& e) { + gml_error_log_exception("get error message: " + string(e.what())); + return NULL; + } + catch (...) { + gml_error_log_exception("get error message"); + return NULL; + } +} + +//################// +//### Internal ###// +//################// + +void gml_error_set_msg(gml_error err, const std::string& msg) { + GmlError* gerr = (GmlError*)err; + gerr->msg = msg; +} + +void gml_error_set_catched_exception_msg(gml_error err) { + gml_error_set_msg(err, "catched unknown exception"); +} + +void gml_error_log_exception(const string& msg) { + if (msg == "") { + cerr << "gml: catched unknown exception" << endl; + } else { + cerr << "gml: catched exception: " << msg << endl; + } +} \ No newline at end of file diff --git a/internal/binding/sources/gml_error.h b/internal/binding/sources/gml_error.h index cc98e1d..c57609d 100644 --- a/internal/binding/sources/gml_error.h +++ b/internal/binding/sources/gml_error.h @@ -25,13 +25,17 @@ * SOFTWARE. */ -#ifndef GML_APP_H -#define GML_APP_H +#ifndef GML_ERROR_H +#define GML_ERROR_H #include "gml_includes.h" -struct GmlError struct { +struct GmlError { string msg; }; +void gml_error_set_msg(gml_error err, const string& msg); +void gml_error_set_catched_exception_msg(gml_error err); +void gml_error_log_exception(const string& msg = ""); + #endif diff --git a/internal/binding/sources/gml_image.cpp b/internal/binding/sources/gml_image.cpp index 529c3bc..e5307b9 100644 --- a/internal/binding/sources/gml_image.cpp +++ b/internal/binding/sources/gml_image.cpp @@ -26,6 +26,7 @@ */ #include "gml_includes.h" +#include "gml_error.h" //#############// //### C API ###// @@ -37,11 +38,11 @@ gml_image gml_image_new() { return (void*)qImg; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception(e.what()); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception(); return NULL; } } @@ -55,18 +56,18 @@ void gml_image_free(gml_image img) { img = NULL; } -int gml_image_load_from_data(gml_image img, char* data, int size) { +int gml_image_load_from_data(gml_image img, char* data, int size, gml_error err) { try { QImage* qImg = (QImage*)img; qImg->loadFromData((const unsigned char*)(data), size); - return 0; // TODO: + return 0; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; - return -1; // TODO: + gml_error_set_msg(err, e.what()); + return -1; } catch (...) { - cerr << "gml: catched variant exception" << endl; - return -1; // TODO: + gml_error_set_catched_exception_msg(err); + return -1; } } diff --git a/internal/binding/sources/gml_imageprovider.cpp b/internal/binding/sources/gml_imageprovider.cpp index a336819..09b03bc 100644 --- a/internal/binding/sources/gml_imageprovider.cpp +++ b/internal/binding/sources/gml_imageprovider.cpp @@ -26,6 +26,7 @@ */ #include "gml_imageprovider.h" +#include "gml_error.h" //########################// //### Static Variables ###// @@ -55,11 +56,11 @@ gml_imageprovider gml_imageprovider_new( return (void*)gip; } catch (std::exception& e) { - //api_error_set_msg(err, e.what()); TODO: + gml_error_log_exception(e.what()); return NULL; } catch (...) { - //api_error_set_unknown_msg(err); TODO: + gml_error_log_exception(); return NULL; } } @@ -79,10 +80,10 @@ void gml_image_response_emit_finished(gml_image_response img_resp, char* error_s gimg_resp->finalize(QString(error_string)); } catch (std::exception& e) { - cerr << "gml: catched image response exception: emit finished: " << e.what() << endl; + gml_error_log_exception("image response: emit finished: " + string(e.what())); } catch (...) { - cerr << "gml: catched image response exception: emit finished: " << endl; + gml_error_log_exception("image response: emit finished"); } } @@ -112,10 +113,10 @@ GmlAsyncImageResponse::GmlAsyncImageResponse( ); } catch (std::exception& e) { - cerr << "gml: catched GmlAsyncImageResponse exception: " << e.what() << endl; + gml_error_log_exception("image async response: request: " + string(e.what())); } catch (...) { - cerr << "gml: catched GmlAsyncImageResponse exception: " << endl; + gml_error_log_exception("image async response: request"); } } @@ -133,7 +134,6 @@ void GmlAsyncImageResponse::finalize(const QString& errorString) { errorStr = errorString; } else if (!requestedSize.isNull() && requestedSize.isValid()) { // Resize the image to the requested size - cout << requestedSize.width() << ", " << requestedSize.height() << endl; img = img.scaled(requestedSize, Qt::IgnoreAspectRatio, transformMode); } diff --git a/internal/binding/sources/gml_includes.h b/internal/binding/sources/gml_includes.h index f65a1be..969694a 100644 --- a/internal/binding/sources/gml_includes.h +++ b/internal/binding/sources/gml_includes.h @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -45,6 +46,7 @@ #include #include +using std::string; using std::cout; using std::cerr; using std::endl; diff --git a/internal/binding/sources/gml_variant.cpp b/internal/binding/sources/gml_variant.cpp index 9a361cc..d144605 100644 --- a/internal/binding/sources/gml_variant.cpp +++ b/internal/binding/sources/gml_variant.cpp @@ -26,6 +26,7 @@ */ #include "gml_includes.h" +#include "gml_error.h" //#############// //### C API ###// @@ -46,11 +47,11 @@ gml_variant gml_variant_new() { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -61,11 +62,11 @@ gml_variant gml_variant_new_from_bool(u_int8_t b) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -76,11 +77,11 @@ gml_variant gml_variant_new_from_float(float f) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -91,11 +92,11 @@ gml_variant gml_variant_new_from_double(double d) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -106,11 +107,11 @@ gml_variant gml_variant_new_from_int(int i) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -121,11 +122,11 @@ gml_variant gml_variant_new_from_int8(int8_t i) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -136,11 +137,11 @@ gml_variant gml_variant_new_from_uint8(u_int8_t i) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -151,11 +152,11 @@ gml_variant gml_variant_new_from_int16(int16_t i) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -166,11 +167,11 @@ gml_variant gml_variant_new_from_uint16(u_int16_t i) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -181,11 +182,11 @@ gml_variant gml_variant_new_from_int32(int32_t i) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -196,11 +197,11 @@ gml_variant gml_variant_new_from_uint32(u_int32_t i) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -211,11 +212,11 @@ gml_variant gml_variant_new_from_int64(int64_t i) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -226,11 +227,11 @@ gml_variant gml_variant_new_from_uint64(u_int64_t i) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -241,11 +242,11 @@ gml_variant gml_variant_new_from_qchar(int32_t r) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -256,11 +257,11 @@ gml_variant gml_variant_new_from_string(char* s) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } @@ -271,11 +272,11 @@ gml_variant gml_variant_new_from_bytes(char* b, int size) { return (void*)v; } catch (std::exception& e) { - cerr << "gml: catched variant exception: " << e.what() << endl; + gml_error_log_exception("variant: " + string(e.what())); return NULL; } catch (...) { - cerr << "gml: catched variant exception" << endl; + gml_error_log_exception("variant"); return NULL; } } \ No newline at end of file diff --git a/internal/build/qtproject.go b/internal/build/qtproject.go index 9ed5cd7..ec9b326 100644 --- a/internal/build/qtproject.go +++ b/internal/build/qtproject.go @@ -32,7 +32,7 @@ import ( "text/template" ) -var qtProTmpl = template.Must(template.New("t").Funcs(tmplFuncMap).Parse(qtProData)) +var qtProTmpl = template.Must(template.New("t").Parse(qtProData)) func prepareQtProject(ctx *Context) (err error) { // Create or open the config file. diff --git a/internal/build/resources.go b/internal/build/resources.go index 54a3839..7c58ce7 100644 --- a/internal/build/resources.go +++ b/internal/build/resources.go @@ -34,7 +34,7 @@ import ( "text/template" ) -var qmlResTmpl = template.Must(template.New("t").Funcs(tmplFuncMap).Parse(qmlResData)) +var qmlResTmpl = template.Must(template.New("t").Parse(qmlResData)) func prepareResources(ctx *Context) (err error) { // Create the resources file. diff --git a/samples/hello_world/main.go b/samples/hello_world/main.go index 2005d11..beb3be3 100644 --- a/samples/hello_world/main.go +++ b/samples/hello_world/main.go @@ -29,7 +29,6 @@ package main import ( "log" - "os" "github.com/desertbit/gml" ) @@ -45,7 +44,7 @@ func main() { log.Fatalln(err) } - os.Exit(app.Exec()) + gml.Exec(app) } const qmlData = ` diff --git a/samples/signals_slots/main.go b/samples/signals_slots/main.go index 6f3324f..6d38213 100644 --- a/samples/signals_slots/main.go +++ b/samples/signals_slots/main.go @@ -30,7 +30,6 @@ package main import ( "io/ioutil" "log" - "os" "github.com/desertbit/gml" _ "github.com/desertbit/gml/samples/signals_slots/testy" @@ -82,5 +81,5 @@ func main() { log.Fatalln(err) } - os.Exit(app.Exec()) + gml.Exec(app) }