| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2017-04-09 21:07:53 +02:00
										 |  |  | /*  gdnative.cpp                                                         */ | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							| 
									
										
										
										
											2017-08-27 14:16:55 +02:00
										 |  |  | /*                      https://godotengine.org                          */ | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2020-01-01 11:16:22 +01:00
										 |  |  | /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* 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.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-09 21:07:53 +02:00
										 |  |  | #include "gdnative.h"
 | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-07 19:33:38 -03:00
										 |  |  | #include "core/config/project_settings.h"
 | 
					
						
							|  |  |  | #include "core/core_constants.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | #include "core/io/file_access_encrypted.h"
 | 
					
						
							|  |  |  | #include "core/os/file_access.h"
 | 
					
						
							|  |  |  | #include "core/os/os.h"
 | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-26 22:58:03 -03:00
										 |  |  | #include "scene/main/scene_tree.h"
 | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-06 12:31:30 +01:00
										 |  |  | static const String init_symbol = "gdnative_init"; | 
					
						
							|  |  |  | static const String terminate_symbol = "gdnative_terminate"; | 
					
						
							|  |  |  | static const String default_symbol_prefix = "godot_"; | 
					
						
							|  |  |  | static const bool default_singleton = false; | 
					
						
							|  |  |  | static const bool default_load_once = true; | 
					
						
							|  |  |  | static const bool default_reloadable = true; | 
					
						
							| 
									
										
										
										
											2017-09-17 16:47:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-03 05:23:05 +02:00
										 |  |  | // Defined in gdnative_api_struct.gen.cpp
 | 
					
						
							| 
									
										
										
										
											2017-11-10 12:08:09 +01:00
										 |  |  | extern const godot_gdnative_core_api_struct api_struct; | 
					
						
							| 
									
										
										
										
											2017-09-17 16:47:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-17 07:33:00 +01:00
										 |  |  | Map<String, Vector<Ref<GDNative>>> GDNativeLibrary::loaded_libraries; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | GDNativeLibrary::GDNativeLibrary() { | 
					
						
							|  |  |  | 	config_file.instance(); | 
					
						
							| 
									
										
										
										
											2017-09-03 14:50:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	symbol_prefix = default_symbol_prefix; | 
					
						
							| 
									
										
										
										
											2018-01-06 12:31:30 +01:00
										 |  |  | 	load_once = default_load_once; | 
					
						
							|  |  |  | 	singleton = default_singleton; | 
					
						
							|  |  |  | 	reloadable = default_reloadable; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | GDNativeLibrary::~GDNativeLibrary() { | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-04 13:06:15 +02:00
										 |  |  | bool GDNativeLibrary::_set(const StringName &p_name, const Variant &p_property) { | 
					
						
							|  |  |  | 	String name = p_name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (name.begins_with("entry/")) { | 
					
						
							|  |  |  | 		String key = name.substr(6, name.length() - 6); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		config_file->set_value("entry", key, p_property); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		set_config_file(config_file); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (name.begins_with("dependency/")) { | 
					
						
							|  |  |  | 		String key = name.substr(11, name.length() - 11); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		config_file->set_value("dependencies", key, p_property); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		set_config_file(config_file); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool GDNativeLibrary::_get(const StringName &p_name, Variant &r_property) const { | 
					
						
							|  |  |  | 	String name = p_name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (name.begins_with("entry/")) { | 
					
						
							|  |  |  | 		String key = name.substr(6, name.length() - 6); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		r_property = config_file->get_value("entry", key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (name.begins_with("dependency/")) { | 
					
						
							|  |  |  | 		String key = name.substr(11, name.length() - 11); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		r_property = config_file->get_value("dependencies", key); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GDNativeLibrary::_get_property_list(List<PropertyInfo> *p_list) const { | 
					
						
							|  |  |  | 	// set entries
 | 
					
						
							|  |  |  | 	List<String> entry_key_list; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (config_file->has_section("entry")) { | 
					
						
							| 
									
										
										
										
											2018-04-04 13:06:15 +02:00
										 |  |  | 		config_file->get_section_keys("entry", &entry_key_list); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-04 13:06:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (List<String>::Element *E = entry_key_list.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 		String key = E->get(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PropertyInfo prop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		prop.type = Variant::STRING; | 
					
						
							|  |  |  | 		prop.name = "entry/" + key; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		p_list->push_back(prop); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// set dependencies
 | 
					
						
							|  |  |  | 	List<String> dependency_key_list; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (config_file->has_section("dependencies")) { | 
					
						
							| 
									
										
										
										
											2018-04-04 13:06:15 +02:00
										 |  |  | 		config_file->get_section_keys("dependencies", &dependency_key_list); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-04 13:06:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for (List<String>::Element *E = dependency_key_list.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 		String key = E->get(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PropertyInfo prop; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		prop.type = Variant::STRING; | 
					
						
							|  |  |  | 		prop.name = "dependency/" + key; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		p_list->push_back(prop); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 20:53:30 +01:00
										 |  |  | void GDNativeLibrary::set_config_file(Ref<ConfigFile> p_config_file) { | 
					
						
							|  |  |  | 	set_singleton(p_config_file->get_value("general", "singleton", default_singleton)); | 
					
						
							|  |  |  | 	set_load_once(p_config_file->get_value("general", "load_once", default_load_once)); | 
					
						
							|  |  |  | 	set_symbol_prefix(p_config_file->get_value("general", "symbol_prefix", default_symbol_prefix)); | 
					
						
							|  |  |  | 	set_reloadable(p_config_file->get_value("general", "reloadable", default_reloadable)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	String entry_lib_path; | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		List<String> entry_keys; | 
					
						
							| 
									
										
										
										
											2018-04-04 13:06:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (p_config_file->has_section("entry")) { | 
					
						
							| 
									
										
										
										
											2018-04-04 13:06:15 +02:00
										 |  |  | 			p_config_file->get_section_keys("entry", &entry_keys); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-25 20:53:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		for (List<String>::Element *E = entry_keys.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 			String key = E->get(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Vector<String> tags = key.split("."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			bool skip = false; | 
					
						
							|  |  |  | 			for (int i = 0; i < tags.size(); i++) { | 
					
						
							|  |  |  | 				bool has_feature = OS::get_singleton()->has_feature(tags[i]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (!has_feature) { | 
					
						
							|  |  |  | 					skip = true; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (skip) { | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			entry_lib_path = p_config_file->get_value("entry", key); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Vector<String> dependency_paths; | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		List<String> dependency_keys; | 
					
						
							| 
									
										
										
										
											2018-04-04 13:06:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (p_config_file->has_section("dependencies")) { | 
					
						
							| 
									
										
										
										
											2018-04-04 13:06:15 +02:00
										 |  |  | 			p_config_file->get_section_keys("dependencies", &dependency_keys); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-25 20:53:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		for (List<String>::Element *E = dependency_keys.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 			String key = E->get(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Vector<String> tags = key.split("."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			bool skip = false; | 
					
						
							|  |  |  | 			for (int i = 0; i < tags.size(); i++) { | 
					
						
							|  |  |  | 				bool has_feature = OS::get_singleton()->has_feature(tags[i]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (!has_feature) { | 
					
						
							|  |  |  | 					skip = true; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (skip) { | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			dependency_paths = p_config_file->get_value("dependencies", key); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	current_library_path = entry_lib_path; | 
					
						
							|  |  |  | 	current_dependencies = dependency_paths; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | void GDNativeLibrary::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_config_file"), &GDNativeLibrary::get_config_file); | 
					
						
							| 
									
										
										
										
											2018-02-25 20:53:30 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_config_file", "config_file"), &GDNativeLibrary::set_config_file); | 
					
						
							| 
									
										
										
										
											2017-07-18 21:43:19 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("get_current_library_path"), &GDNativeLibrary::get_current_library_path); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_current_dependencies"), &GDNativeLibrary::get_current_dependencies); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("should_load_once"), &GDNativeLibrary::should_load_once); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("is_singleton"), &GDNativeLibrary::is_singleton); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_symbol_prefix"), &GDNativeLibrary::get_symbol_prefix); | 
					
						
							| 
									
										
										
										
											2018-01-06 12:31:30 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("is_reloadable"), &GDNativeLibrary::is_reloadable); | 
					
						
							| 
									
										
										
										
											2017-07-18 21:43:19 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_load_once", "load_once"), &GDNativeLibrary::set_load_once); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_singleton", "singleton"), &GDNativeLibrary::set_singleton); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_symbol_prefix", "symbol_prefix"), &GDNativeLibrary::set_symbol_prefix); | 
					
						
							| 
									
										
										
										
											2018-01-06 12:31:30 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_reloadable", "reloadable"), &GDNativeLibrary::set_reloadable); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-12 15:36:38 +02:00
										 |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "config_file", PROPERTY_HINT_RESOURCE_TYPE, "ConfigFile", 0), "set_config_file", "get_config_file"); | 
					
						
							| 
									
										
										
										
											2018-02-25 20:53:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-08 11:30:02 -03:00
										 |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "load_once"), "set_load_once", "should_load_once"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "singleton"), "set_singleton", "is_singleton"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::STRING, "symbol_prefix"), "set_symbol_prefix", "get_symbol_prefix"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reloadable"), "set_reloadable", "is_reloadable"); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | GDNative::GDNative() { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	native_handle = nullptr; | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	initialized = false; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | GDNative::~GDNative() { | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | void GDNative::_bind_methods() { | 
					
						
							| 
									
										
										
										
											2017-08-09 13:19:41 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_library", "library"), &GDNative::set_library); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_library"), &GDNative::get_library); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("initialize"), &GDNative::initialize); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("terminate"), &GDNative::terminate); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-14 15:42:10 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("call_native", "calling_type", "procedure_name", "arguments"), &GDNative::call_native); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-08 11:30:02 -03:00
										 |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "library", PROPERTY_HINT_RESOURCE_TYPE, "GDNativeLibrary"), "set_library", "get_library"); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | void GDNative::set_library(Ref<GDNativeLibrary> p_library) { | 
					
						
							| 
									
										
										
										
											2019-08-09 06:49:33 +02:00
										 |  |  | 	ERR_FAIL_COND_MSG(library.is_valid(), "Tried to change library of GDNative when it is already set."); | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	library = p_library; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | Ref<GDNativeLibrary> GDNative::get_library() const { | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	return library; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-19 23:41:22 +01:00
										 |  |  | extern "C" void _gdnative_report_version_mismatch(const godot_object *p_library, const char *p_ext, godot_gdnative_api_version p_want, godot_gdnative_api_version p_have); | 
					
						
							|  |  |  | extern "C" void _gdnative_report_loading_error(const godot_object *p_library, const char *p_what); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | bool GDNative::initialize() { | 
					
						
							|  |  |  | 	if (library.is_null()) { | 
					
						
							|  |  |  | 		ERR_PRINT("No library set, can't initialize GDNative object"); | 
					
						
							|  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	String lib_path = library->get_current_library_path(); | 
					
						
							| 
									
										
										
										
											2017-11-20 14:28:52 +01:00
										 |  |  | 	if (lib_path.empty()) { | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 		ERR_PRINT("No library set for this platform"); | 
					
						
							|  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-04 20:10:03 +07:00
										 |  |  | #ifdef IPHONE_ENABLED
 | 
					
						
							| 
									
										
										
										
											2020-07-02 12:38:51 +03:00
										 |  |  | 	// On iOS we use static linking by default.
 | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 	String path = ""; | 
					
						
							| 
									
										
										
										
											2020-07-02 12:38:51 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// On iOS dylibs is not allowed, but can be replaced with .framework or .xcframework.
 | 
					
						
							|  |  |  | 	// If they are used, we can run dlopen on them.
 | 
					
						
							|  |  |  | 	// They should be located under Frameworks directory, so we need to replace library path.
 | 
					
						
							|  |  |  | 	if (!lib_path.ends_with(".a")) { | 
					
						
							|  |  |  | 		path = ProjectSettings::get_singleton()->globalize_path(lib_path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!FileAccess::exists(path)) { | 
					
						
							|  |  |  | 			String lib_name = lib_path.get_basename().get_file(); | 
					
						
							|  |  |  | 			String framework_path_format = "Frameworks/$name.framework/$name"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Dictionary format_dict; | 
					
						
							|  |  |  | 			format_dict["name"] = lib_name; | 
					
						
							|  |  |  | 			String framework_path = framework_path_format.format(format_dict, "$_"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			path = OS::get_singleton()->get_executable_path().get_base_dir().plus_file(framework_path); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-21 01:12:36 +07:00
										 |  |  | #elif defined(ANDROID_ENABLED)
 | 
					
						
							|  |  |  | 	// On Android dynamic libraries are located separately from resource assets,
 | 
					
						
							|  |  |  | 	// we should pass library name to dlopen(). The library name is flattened
 | 
					
						
							|  |  |  | 	// during export.
 | 
					
						
							|  |  |  | 	String path = lib_path.get_file(); | 
					
						
							| 
									
										
										
										
											2018-01-01 13:59:13 -02:00
										 |  |  | #elif defined(UWP_ENABLED)
 | 
					
						
							|  |  |  | 	// On UWP we use a relative path from the app
 | 
					
						
							|  |  |  | 	String path = lib_path.replace("res://", ""); | 
					
						
							| 
									
										
										
										
											2018-10-28 00:58:04 +09:00
										 |  |  | #elif defined(OSX_ENABLED)
 | 
					
						
							|  |  |  | 	// On OSX the exported libraries are located under the Frameworks directory.
 | 
					
						
							|  |  |  | 	// So we need to replace the library path.
 | 
					
						
							|  |  |  | 	String path = ProjectSettings::get_singleton()->globalize_path(lib_path); | 
					
						
							|  |  |  | 	if (!FileAccess::exists(path)) { | 
					
						
							|  |  |  | 		path = OS::get_singleton()->get_executable_path().get_base_dir().plus_file("../Frameworks").plus_file(lib_path.get_file()); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-04 20:10:03 +07:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	String path = ProjectSettings::get_singleton()->globalize_path(lib_path); | 
					
						
							| 
									
										
										
										
											2017-09-04 20:10:03 +07:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (library->should_load_once()) { | 
					
						
							| 
									
										
										
										
											2019-07-02 17:23:54 +03:00
										 |  |  | 		if (GDNativeLibrary::loaded_libraries.has(lib_path)) { | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 			// already loaded. Don't load again.
 | 
					
						
							|  |  |  | 			// copy some of the stuff instead
 | 
					
						
							| 
									
										
										
										
											2019-07-02 17:23:54 +03:00
										 |  |  | 			this->native_handle = GDNativeLibrary::loaded_libraries[lib_path][0]->native_handle; | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 			initialized = true; | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-06 19:54:22 +01:00
										 |  |  | 	Error err = OS::get_singleton()->open_dynamic_library(path, native_handle, true); | 
					
						
							| 
									
										
										
										
											2017-11-20 14:28:52 +01:00
										 |  |  | 	if (err != OK) { | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	void *library_init; | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// we cheat here a little bit. you saw nothing
 | 
					
						
							|  |  |  | 	initialized = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 	err = get_symbol(library->get_symbol_prefix() + init_symbol, library_init, false); | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	initialized = false; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	if (err || !library_init) { | 
					
						
							| 
									
										
										
										
											2017-11-20 14:28:52 +01:00
										 |  |  | 		OS::get_singleton()->close_dynamic_library(native_handle); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		native_handle = nullptr; | 
					
						
							| 
									
										
										
										
											2019-11-06 17:03:04 +01:00
										 |  |  | 		ERR_PRINT("Failed to obtain " + library->get_symbol_prefix() + "gdnative_init symbol"); | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-08 01:28:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	godot_gdnative_init_fn library_init_fpointer; | 
					
						
							|  |  |  | 	library_init_fpointer = (godot_gdnative_init_fn)library_init; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-13 21:21:05 +01:00
										 |  |  | 	static uint64_t core_api_hash = 0; | 
					
						
							|  |  |  | 	static uint64_t editor_api_hash = 0; | 
					
						
							|  |  |  | 	static uint64_t no_api_hash = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!(core_api_hash || editor_api_hash || no_api_hash)) { | 
					
						
							|  |  |  | 		core_api_hash = ClassDB::get_api_hash(ClassDB::API_CORE); | 
					
						
							|  |  |  | 		editor_api_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR); | 
					
						
							|  |  |  | 		no_api_hash = ClassDB::get_api_hash(ClassDB::API_NONE); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	godot_gdnative_init_options options; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-15 17:18:28 +02:00
										 |  |  | 	options.api_struct = &api_struct; | 
					
						
							| 
									
										
										
										
											2017-08-19 01:02:56 +02:00
										 |  |  | 	options.in_editor = Engine::get_singleton()->is_editor_hint(); | 
					
						
							| 
									
										
										
										
											2018-01-13 21:21:05 +01:00
										 |  |  | 	options.core_api_hash = core_api_hash; | 
					
						
							|  |  |  | 	options.editor_api_hash = editor_api_hash; | 
					
						
							|  |  |  | 	options.no_api_hash = no_api_hash; | 
					
						
							| 
									
										
										
										
											2017-11-19 23:41:22 +01:00
										 |  |  | 	options.report_version_mismatch = &_gdnative_report_version_mismatch; | 
					
						
							|  |  |  | 	options.report_loading_error = &_gdnative_report_loading_error; | 
					
						
							| 
									
										
										
										
											2017-07-28 22:43:23 +07:00
										 |  |  | 	options.gd_native_library = (godot_object *)(get_library().ptr()); | 
					
						
							| 
									
										
										
										
											2017-10-02 13:45:47 +02:00
										 |  |  | 	options.active_library_path = (godot_string *)&path; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	library_init_fpointer(&options); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	initialized = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 17:23:54 +03:00
										 |  |  | 	if (library->should_load_once() && !GDNativeLibrary::loaded_libraries.has(lib_path)) { | 
					
						
							| 
									
										
										
										
											2020-03-17 07:33:00 +01:00
										 |  |  | 		Vector<Ref<GDNative>> gdnatives; | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 		gdnatives.resize(1); | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		gdnatives.write[0] = Ref<GDNative>(this); | 
					
						
							| 
									
										
										
										
											2019-07-02 17:23:54 +03:00
										 |  |  | 		GDNativeLibrary::loaded_libraries.insert(lib_path, gdnatives); | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | bool GDNative::terminate() { | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	if (!initialized) { | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 		ERR_PRINT("No valid library handle, can't terminate GDNative object"); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	if (library->should_load_once()) { | 
					
						
							| 
									
										
										
										
											2020-03-17 07:33:00 +01:00
										 |  |  | 		Vector<Ref<GDNative>> *gdnatives = &GDNativeLibrary::loaded_libraries[library->get_current_library_path()]; | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 		if (gdnatives->size() > 1) { | 
					
						
							| 
									
										
										
										
											2018-09-12 21:38:39 -04:00
										 |  |  | 			// there are other GDNative's still using this library, so we actually don't terminate
 | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 			gdnatives->erase(Ref<GDNative>(this)); | 
					
						
							|  |  |  | 			initialized = false; | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 		} else if (gdnatives->size() == 1) { | 
					
						
							|  |  |  | 			// we're the last one, terminate!
 | 
					
						
							|  |  |  | 			gdnatives->clear(); | 
					
						
							| 
									
										
										
										
											2019-05-19 12:34:40 +02:00
										 |  |  | 			// whew this looks scary, but all it does is remove the entry completely
 | 
					
						
							| 
									
										
										
										
											2019-07-02 17:23:54 +03:00
										 |  |  | 			GDNativeLibrary::loaded_libraries.erase(GDNativeLibrary::loaded_libraries.find(library->get_current_library_path())); | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	void *library_terminate; | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	Error error = get_symbol(library->get_symbol_prefix() + terminate_symbol, library_terminate); | 
					
						
							| 
									
										
										
										
											2017-10-14 15:42:10 +02:00
										 |  |  | 	if (error || !library_terminate) { | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 		OS::get_singleton()->close_dynamic_library(native_handle); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 		native_handle = nullptr; | 
					
						
							| 
									
										
										
										
											2019-03-09 18:01:08 +01:00
										 |  |  | 		initialized = false; | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	godot_gdnative_terminate_fn library_terminate_pointer; | 
					
						
							|  |  |  | 	library_terminate_pointer = (godot_gdnative_terminate_fn)library_terminate; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	godot_gdnative_terminate_options options; | 
					
						
							| 
									
										
										
										
											2017-08-19 01:02:56 +02:00
										 |  |  | 	options.in_editor = Engine::get_singleton()->is_editor_hint(); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	library_terminate_pointer(&options); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	initialized = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	// GDNativeScriptLanguage::get_singleton()->initialized_libraries.erase(p_native_lib->path);
 | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	OS::get_singleton()->close_dynamic_library(native_handle); | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	native_handle = nullptr; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-04 21:17:33 +07:00
										 |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | bool GDNative::is_initialized() const { | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	return initialized; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | void GDNativeCallRegistry::register_native_call_type(StringName p_call_type, native_call_cb p_callback) { | 
					
						
							|  |  |  | 	native_calls.insert(p_call_type, p_callback); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | Vector<StringName> GDNativeCallRegistry::get_native_call_types() { | 
					
						
							|  |  |  | 	Vector<StringName> call_types; | 
					
						
							|  |  |  | 	call_types.resize(native_calls.size()); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	size_t idx = 0; | 
					
						
							|  |  |  | 	for (Map<StringName, native_call_cb>::Element *E = native_calls.front(); E; E = E->next(), idx++) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		call_types.write[idx] = E->key(); | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	return call_types; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | Variant GDNative::call_native(StringName p_native_call_type, StringName p_procedure_name, Array p_arguments) { | 
					
						
							|  |  |  | 	Map<StringName, native_call_cb>::Element *E = GDNativeCallRegistry::singleton->native_calls.find(p_native_call_type); | 
					
						
							|  |  |  | 	if (!E) { | 
					
						
							|  |  |  | 		ERR_PRINT((String("No handler for native call type \"" + p_native_call_type) + "\" found").utf8().get_data()); | 
					
						
							|  |  |  | 		return Variant(); | 
					
						
							| 
									
										
										
										
											2017-04-08 01:28:14 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-14 15:42:10 +02:00
										 |  |  | 	void *procedure_handle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Error err = OS::get_singleton()->get_dynamic_library_symbol_handle( | 
					
						
							|  |  |  | 			native_handle, | 
					
						
							|  |  |  | 			p_procedure_name, | 
					
						
							|  |  |  | 			procedure_handle); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	if (err != OK || procedure_handle == nullptr) { | 
					
						
							| 
									
										
										
										
											2017-10-14 15:42:10 +02:00
										 |  |  | 		return Variant(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	godot_variant result = E->get()(procedure_handle, (godot_array *)&p_arguments); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-08 21:23:59 +02:00
										 |  |  | 	Variant res = *(Variant *)&result; | 
					
						
							|  |  |  | 	godot_variant_destroy(&result); | 
					
						
							|  |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle, bool p_optional) const { | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	if (!initialized) { | 
					
						
							| 
									
										
										
										
											2017-10-14 15:42:10 +02:00
										 |  |  | 		ERR_PRINT("No valid library handle, can't get symbol from GDNative object"); | 
					
						
							|  |  |  | 		return ERR_CANT_OPEN; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-14 15:42:10 +02:00
										 |  |  | 	Error result = OS::get_singleton()->get_dynamic_library_symbol_handle( | 
					
						
							|  |  |  | 			native_handle, | 
					
						
							|  |  |  | 			p_procedure_name, | 
					
						
							|  |  |  | 			r_handle, | 
					
						
							| 
									
										
										
										
											2017-10-02 22:01:43 +07:00
										 |  |  | 			p_optional); | 
					
						
							| 
									
										
										
										
											2017-10-14 15:42:10 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return result; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-19 23:19:21 -03:00
										 |  |  | RES GDNativeLibraryResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	Ref<GDNativeLibrary> lib; | 
					
						
							|  |  |  | 	lib.instance(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Ref<ConfigFile> config = lib->get_config_file(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Error err = config->load(p_path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (r_error) { | 
					
						
							|  |  |  | 		*r_error = err; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 20:53:30 +01:00
										 |  |  | 	lib->set_config_file(config); | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return lib; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GDNativeLibraryResourceLoader::get_recognized_extensions(List<String> *p_extensions) const { | 
					
						
							|  |  |  | 	p_extensions->push_back("gdnlib"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool GDNativeLibraryResourceLoader::handles_type(const String &p_type) const { | 
					
						
							| 
									
										
										
										
											2017-11-02 19:01:30 +01:00
										 |  |  | 	return p_type == "GDNativeLibrary"; | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String GDNativeLibraryResourceLoader::get_resource_type(const String &p_path) const { | 
					
						
							|  |  |  | 	String el = p_path.get_extension().to_lower(); | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	if (el == "gdnlib") { | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 		return "GDNativeLibrary"; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 	return ""; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Error GDNativeLibraryResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { | 
					
						
							|  |  |  | 	Ref<GDNativeLibrary> lib = p_resource; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (lib.is_null()) { | 
					
						
							|  |  |  | 		return ERR_INVALID_DATA; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Ref<ConfigFile> config = lib->get_config_file(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	config->set_value("general", "singleton", lib->is_singleton()); | 
					
						
							|  |  |  | 	config->set_value("general", "load_once", lib->should_load_once()); | 
					
						
							|  |  |  | 	config->set_value("general", "symbol_prefix", lib->get_symbol_prefix()); | 
					
						
							| 
									
										
										
										
											2018-01-06 12:31:30 +01:00
										 |  |  | 	config->set_value("general", "reloadable", lib->is_reloadable()); | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return config->save(p_path); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool GDNativeLibraryResourceSaver::recognize(const RES &p_resource) const { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	return Object::cast_to<GDNativeLibrary>(*p_resource) != nullptr; | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GDNativeLibraryResourceSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { | 
					
						
							| 
									
										
										
										
											2020-04-02 01:20:12 +02:00
										 |  |  | 	if (Object::cast_to<GDNativeLibrary>(*p_resource) != nullptr) { | 
					
						
							| 
									
										
										
										
											2017-11-02 17:14:37 +01:00
										 |  |  | 		p_extensions->push_back("gdnlib"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |