Browse Source

Merge pull request #9907 from karroffel/nativescript-init-call

NativeScript changes and OS symbol lookup optional error handling
Thomas Herzog 8 years ago
parent
commit
3c53b3560f

+ 3 - 3
core/os/os.h

@@ -184,9 +184,9 @@ public:
 
 	virtual void set_ime_position(const Point2 &p_pos) {}
 
-	virtual Error open_dynamic_library(const String p_path, void *&p_library_handle) { return ERR_UNAVAILABLE; };
-	virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; };
-	virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle) { return ERR_UNAVAILABLE; };
+	virtual Error open_dynamic_library(const String p_path, void *&p_library_handle) { return ERR_UNAVAILABLE; }
+	virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; }
+	virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) { return ERR_UNAVAILABLE; }
 
 	virtual void set_keep_screen_on(bool p_enabled);
 	virtual bool is_keep_screen_on() const;

+ 7 - 3
drivers/unix/os_unix.cpp

@@ -453,7 +453,7 @@ Error OS_Unix::close_dynamic_library(void *p_library_handle) {
 	return OK;
 }
 
-Error OS_Unix::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle) {
+Error OS_Unix::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) {
 	const char *error;
 	dlerror(); // Clear existing errors
 
@@ -461,8 +461,12 @@ Error OS_Unix::get_dynamic_library_symbol_handle(void *p_library_handle, const S
 
 	error = dlerror();
 	if (error != NULL) {
-		ERR_EXPLAIN("Can't resolve symbol " + p_name + ". Error: " + error);
-		ERR_FAIL_V(ERR_CANT_RESOLVE);
+		if (!p_optional) {
+			ERR_EXPLAIN("Can't resolve symbol " + p_name + ". Error: " + error);
+			ERR_FAIL_V(ERR_CANT_RESOLVE);
+		} else {
+			return ERR_CANT_RESOLVE;
+		}
 	}
 	return OK;
 }

+ 1 - 1
drivers/unix/os_unix.h

@@ -85,7 +85,7 @@ public:
 
 	virtual Error open_dynamic_library(const String p_path, void *&p_library_handle);
 	virtual Error close_dynamic_library(void *p_library_handle);
-	virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle);
+	virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false);
 
 	virtual Error set_cwd(const String &p_cwd);
 

+ 2 - 1
modules/gdnative/register_types.cpp

@@ -47,7 +47,8 @@ godot_variant cb_standard_varcall(void *handle, godot_string *p_procedure, godot
 	Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(
 			handle,
 			*(String *)p_procedure,
-			library_proc);
+			library_proc,
+			true); // we roll our own message
 	if (err != OK) {
 		ERR_PRINT((String("GDNative procedure \"" + *(String *)p_procedure) + "\" does not exists and can't be called").utf8().get_data());
 		godot_variant ret;

+ 42 - 3
modules/nativescript/nativescript.cpp

@@ -203,7 +203,15 @@ ScriptInstance *NativeScript::instance_create(Object *p_this) {
 	nsi->userdata = script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data);
 #endif
 
+#ifndef NO_THREADS
+	owners_lock->lock();
+#endif
+
 	instance_owners.insert(p_this);
+
+#ifndef NO_THREADS
+	owners_lock->unlock();
+#endif
 	return nsi;
 }
 
@@ -393,9 +401,6 @@ Variant NativeScript::_new(const Variant **p_args, int p_argcount, Variant::Call
 		ref = REF(r);
 	}
 
-	// GDScript does it like this: _create_instance(p_args, p_argcount, owner, r != NULL, r_error);
-	// TODO(karroffel): support varargs for constructors.
-
 	NativeScriptInstance *instance = (NativeScriptInstance *)instance_create(owner);
 
 	owner->set_script_instance(instance);
@@ -407,6 +412,24 @@ Variant NativeScript::_new(const Variant **p_args, int p_argcount, Variant::Call
 		return Variant();
 	}
 
+	call("_init", p_args, p_argcount, r_error);
+
+	if (r_error.error != Variant::CallError::CALL_OK) {
+		instance->script = Ref<NativeScript>();
+		instance->owner->set_script_instance(NULL);
+
+#ifndef NO_THREADS
+		owners_lock->lock();
+#endif
+		instance_owners.erase(owner);
+
+#ifndef NO_THREADS
+		owners_lock->unlock();
+#endif
+
+		ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, Variant());
+	}
+
 	if (ref.is_valid()) {
 		return ref;
 	} else {
@@ -419,11 +442,18 @@ NativeScript::NativeScript() {
 	library = Ref<GDNative>();
 	lib_path = "";
 	class_name = "";
+#ifndef NO_THREADS
+	owners_lock = Mutex::create();
+#endif
 }
 
 // TODO(karroffel): implement this
 NativeScript::~NativeScript() {
 	NSL->unregister_script(this);
+
+#ifndef NO_THREADS
+	memdelete(owners_lock);
+#endif
 }
 
 ////// ScriptInstance stuff
@@ -754,7 +784,16 @@ NativeScriptInstance::~NativeScriptInstance() {
 	script_data->destroy_func.destroy_func((godot_object *)owner, script_data->destroy_func.method_data, userdata);
 
 	if (owner) {
+
+#ifndef NO_THREADS
+		script->owners_lock->lock();
+#endif
+
 		script->instance_owners.erase(owner);
+
+#ifndef NO_THREADS
+		script->owners_lock->lock();
+#endif
 	}
 }
 

+ 3 - 0
modules/nativescript/nativescript.h

@@ -106,6 +106,9 @@ class NativeScript : public Script {
 
 	String class_name;
 
+#ifndef NO_THREADS
+	Mutex *owners_lock;
+#endif
 	Set<Object *> instance_owners;
 
 protected:

+ 4 - 2
modules/nativescript/register_types.cpp

@@ -50,7 +50,8 @@ void init_call_cb(void *p_handle, godot_string *p_proc_name, void *p_data, int p
 	Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(
 			p_handle,
 			*(String *)p_proc_name,
-			library_proc);
+			library_proc,
+			true); // we print our own message
 	if (err != OK) {
 		ERR_PRINT((String("GDNative procedure \"" + *(String *)p_proc_name) + "\" does not exists and can't be called").utf8().get_data());
 		return;
@@ -75,7 +76,8 @@ void thread_call_cb(void *p_handle, godot_string *p_proc_name, void *p_data, int
 	Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(
 			p_handle,
 			*(String *)p_proc_name,
-			library_proc);
+			library_proc,
+			true);
 	if (err != OK) {
 		// it's fine if thread callbacks are not present in the library.
 		return;

+ 7 - 3
platform/windows/os_windows.cpp

@@ -1569,12 +1569,16 @@ Error OS_Windows::close_dynamic_library(void *p_library_handle) {
 	return OK;
 }
 
-Error OS_Windows::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle) {
+Error OS_Windows::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) {
 	char *error;
 	p_symbol_handle = (void *)GetProcAddress((HMODULE)p_library_handle, p_name.utf8().get_data());
 	if (!p_symbol_handle) {
-		ERR_EXPLAIN("Can't resolve symbol " + p_name + ". Error: " + String::num(GetLastError()));
-		ERR_FAIL_V(ERR_CANT_RESOLVE);
+		if (!p_optional) {
+			ERR_EXPLAIN("Can't resolve symbol " + p_name + ". Error: " + String::num(GetLastError()));
+			ERR_FAIL_V(ERR_CANT_RESOLVE);
+		} else {
+			return ERR_CANT_RESOLVE;
+		}
 	}
 	return OK;
 }

+ 1 - 1
platform/windows/os_windows.h

@@ -227,7 +227,7 @@ public:
 
 	virtual Error open_dynamic_library(const String p_path, void *&p_library_handle);
 	virtual Error close_dynamic_library(void *p_library_handle);
-	virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle);
+	virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false);
 
 	virtual MainLoop *get_main_loop() const;