| 
									
										
										
										
											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
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							| 
									
										
										
										
											2017-04-08 00:11:42 +02:00
										 |  |  | /* Copyright (c) 2014-2017 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.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2017-04-09 21:07:53 +02:00
										 |  |  | #include "gdnative.h"
 | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "global_constants.h"
 | 
					
						
							|  |  |  | #include "io/file_access_encrypted.h"
 | 
					
						
							|  |  |  | #include "os/file_access.h"
 | 
					
						
							|  |  |  | #include "os/os.h"
 | 
					
						
							| 
									
										
										
										
											2017-07-19 17:00:46 -03:00
										 |  |  | #include "project_settings.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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | const String init_symbol = "godot_gdnative_init"; | 
					
						
							|  |  |  | const String terminate_symbol = "godot_gdnative_terminate"; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | String GDNativeLibrary::platform_names[NUM_PLATFORMS] = { | 
					
						
							|  |  |  | 	"X11_32bit", | 
					
						
							|  |  |  | 	"X11_64bit", | 
					
						
							|  |  |  | 	"Windows_32bit", | 
					
						
							|  |  |  | 	"Windows_64bit", | 
					
						
							|  |  |  | 	"OSX", | 
					
						
							| 
									
										
										
										
											2017-04-08 01:28:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	"Android", | 
					
						
							|  |  |  | 	"iOS", | 
					
						
							| 
									
										
										
										
											2017-04-07 04:47:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	"WebAssembly" | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | String GDNativeLibrary::platform_lib_ext[NUM_PLATFORMS] = { | 
					
						
							|  |  |  | 	"so", | 
					
						
							|  |  |  | 	"so", | 
					
						
							|  |  |  | 	"dll", | 
					
						
							|  |  |  | 	"dll", | 
					
						
							|  |  |  | 	"dylib", | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	"so", | 
					
						
							|  |  |  | 	"dylib", | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	"wasm" | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-24 22:43:32 +02:00
										 |  |  | // TODO(karroffel): make this actually do the right thing.
 | 
					
						
							|  |  |  | GDNativeLibrary::Platform GDNativeLibrary::current_platform = | 
					
						
							|  |  |  | #if defined(X11_ENABLED)
 | 
					
						
							|  |  |  | 		X11_64BIT; | 
					
						
							|  |  |  | #elif defined(WINDOWS_ENABLED)
 | 
					
						
							|  |  |  | 		WINDOWS_64BIT; | 
					
						
							|  |  |  | #elif defined(OSX_ENABLED)
 | 
					
						
							|  |  |  | 		OSX; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 		X11_64BIT; // need a sensible default..
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | GDNativeLibrary::GDNativeLibrary() | 
					
						
							|  |  |  | 	: library_paths() { | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | GDNativeLibrary::~GDNativeLibrary() { | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | void GDNativeLibrary::_bind_methods() { | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_library_path", "platform", "path"), &GDNativeLibrary::set_library_path); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_library_path", "platform"), &GDNativeLibrary::get_library_path); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-09 21:07:53 +02:00
										 |  |  | bool GDNativeLibrary::_set(const StringName &p_name, const Variant &p_value) { | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	String name = p_name; | 
					
						
							|  |  |  | 	if (name.begins_with("platform/")) { | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 		set_library_path(name.get_slice("/", 1), p_value); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-09 21:07:53 +02:00
										 |  |  | bool GDNativeLibrary::_get(const StringName &p_name, Variant &r_ret) const { | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	String name = p_name; | 
					
						
							|  |  |  | 	if (name.begins_with("platform/")) { | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 		r_ret = get_library_path(name.get_slice("/", 1)); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-09 21:07:53 +02:00
										 |  |  | void GDNativeLibrary::_get_property_list(List<PropertyInfo> *p_list) const { | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	for (int i = 0; i < NUM_PLATFORMS; i++) { | 
					
						
							|  |  |  | 		p_list->push_back(PropertyInfo(Variant::STRING, | 
					
						
							|  |  |  | 				"platform/" + platform_names[i], | 
					
						
							|  |  |  | 				PROPERTY_HINT_FILE, | 
					
						
							|  |  |  | 				"*." + platform_lib_ext[i])); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | void GDNativeLibrary::set_library_path(StringName p_platform, String p_path) { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	for (i = 0; i <= NUM_PLATFORMS; i++) { | 
					
						
							|  |  |  | 		if (i == NUM_PLATFORMS) break; | 
					
						
							|  |  |  | 		if (platform_names[i] == p_platform) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-07-18 21:43:19 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	if (i == NUM_PLATFORMS) { | 
					
						
							|  |  |  | 		ERR_EXPLAIN(String("No such platform: ") + p_platform); | 
					
						
							|  |  |  | 		ERR_FAIL(); | 
					
						
							| 
									
										
										
										
											2017-07-18 21:43:19 +05:30
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	library_paths[i] = p_path; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | String GDNativeLibrary::get_library_path(StringName p_platform) const { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	for (i = 0; i <= NUM_PLATFORMS; i++) { | 
					
						
							|  |  |  | 		if (i == NUM_PLATFORMS) break; | 
					
						
							|  |  |  | 		if (platform_names[i] == p_platform) { | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2017-07-22 06:05:59 +05:30
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-07-18 21:43:19 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	if (i == NUM_PLATFORMS) { | 
					
						
							|  |  |  | 		ERR_EXPLAIN(String("No such platform: ") + p_platform); | 
					
						
							|  |  |  | 		ERR_FAIL_V(""); | 
					
						
							| 
									
										
										
										
											2017-07-18 21:43:19 +05:30
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	return library_paths[i]; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | String GDNativeLibrary::get_active_library_path() const { | 
					
						
							|  |  |  | 	return library_paths[GDNativeLibrary::current_platform]; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | GDNative::GDNative() { | 
					
						
							|  |  |  | 	native_handle = NULL; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | GDNative::~GDNative() { | 
					
						
							|  |  |  | 	// TODO(karroffel): implement ALL the things!
 | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | extern "C" void _api_anchor(); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | void GDNative::_compile_dummy_for_api() { | 
					
						
							|  |  |  | 	_api_anchor(); | 
					
						
							| 
									
										
										
										
											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-07-14 01:44:14 +02:00
										 |  |  | 	// TODO(karroffel): get_native_(raw_)call_types binding?
 | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	// TODO(karroffel): make this a varargs function?
 | 
					
						
							| 
									
										
										
										
											2017-08-09 13:19:41 +02:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("call_native", "procedure_name", "arguments"), &GDNative::call_native); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	ADD_PROPERTYNZ(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) { | 
					
						
							| 
									
										
										
										
											2017-07-28 22:43:23 +07:00
										 |  |  | 	ERR_EXPLAIN("Tried to change library of GDNative when it is already set"); | 
					
						
							|  |  |  | 	ERR_FAIL_COND(library.is_valid()); | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	library = p_library; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | Ref<GDNativeLibrary> GDNative::get_library() { | 
					
						
							|  |  |  | 	return library; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-07-14 01:44:14 +02:00
										 |  |  | 	String lib_path = library->get_active_library_path(); | 
					
						
							|  |  |  | 	if (lib_path.empty()) { | 
					
						
							|  |  |  | 		ERR_PRINT("No library set for this platform"); | 
					
						
							|  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	String path = ProjectSettings::get_singleton()->globalize_path(lib_path); | 
					
						
							|  |  |  | 	Error err = OS::get_singleton()->open_dynamic_library(path, native_handle); | 
					
						
							|  |  |  | 	if (err != OK) { | 
					
						
							|  |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	void *library_init; | 
					
						
							|  |  |  | 	err = OS::get_singleton()->get_dynamic_library_symbol_handle( | 
					
						
							|  |  |  | 			native_handle, | 
					
						
							|  |  |  | 			init_symbol, | 
					
						
							|  |  |  | 			library_init); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	if (err || !library_init) { | 
					
						
							| 
									
										
										
										
											2017-08-04 21:17:33 +07:00
										 |  |  | 		OS::get_singleton()->close_dynamic_library(native_handle); | 
					
						
							|  |  |  | 		native_handle = NULL; | 
					
						
							|  |  |  | 		ERR_PRINT("Failed to obtain godot_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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	godot_gdnative_init_options options; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-19 01:02:56 +02:00
										 |  |  | 	options.in_editor = Engine::get_singleton()->is_editor_hint(); | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	options.core_api_hash = ClassDB::get_api_hash(ClassDB::API_CORE); | 
					
						
							|  |  |  | 	options.editor_api_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR); | 
					
						
							|  |  |  | 	options.no_api_hash = ClassDB::get_api_hash(ClassDB::API_NONE); | 
					
						
							| 
									
										
										
										
											2017-07-28 22:43:23 +07:00
										 |  |  | 	options.gd_native_library = (godot_object *)(get_library().ptr()); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | bool GDNative::terminate() { | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	if (native_handle == NULL) { | 
					
						
							|  |  |  | 		ERR_PRINT("No valid library handle, can't terminate GDNative object"); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	void *library_terminate; | 
					
						
							| 
									
										
										
										
											2017-08-21 15:15:36 -04:00
										 |  |  | 	Error error = OS::get_singleton()->get_dynamic_library_symbol_handle( | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 			native_handle, | 
					
						
							|  |  |  | 			terminate_symbol, | 
					
						
							|  |  |  | 			library_terminate); | 
					
						
							|  |  |  | 	if (error) { | 
					
						
							|  |  |  | 		OS::get_singleton()->close_dynamic_library(native_handle); | 
					
						
							|  |  |  | 		native_handle = NULL; | 
					
						
							|  |  |  | 		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
										 |  |  | 	// TODO(karroffel): remove this? Should be part of NativeScript, not
 | 
					
						
							|  |  |  | 	// GDNative IMO
 | 
					
						
							|  |  |  | 	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-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); | 
					
						
							|  |  |  | 	native_handle = NULL; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-04 21:17:33 +07:00
										 |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool GDNative::is_initialized() { | 
					
						
							|  |  |  | 	return (native_handle != NULL); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | void GDNativeCallRegistry::register_native_raw_call_type(StringName p_raw_call_type, native_raw_call_cb p_callback) { | 
					
						
							|  |  |  | 	native_raw_calls.insert(p_raw_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++) { | 
					
						
							|  |  |  | 		call_types[idx] = E->key(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											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
										 |  |  | Vector<StringName> GDNativeCallRegistry::get_native_raw_call_types() { | 
					
						
							|  |  |  | 	Vector<StringName> call_types; | 
					
						
							|  |  |  | 	call_types.resize(native_raw_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_raw_call_cb>::Element *E = native_raw_calls.front(); E; E = E->next(), idx++) { | 
					
						
							|  |  |  | 		call_types[idx] = E->key(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-08 01:28:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	return call_types; | 
					
						
							| 
									
										
										
										
											2017-04-08 01:28:14 +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) { | 
					
						
							| 
									
										
										
										
											2017-05-13 14:37:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	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-07-14 01:44:14 +02:00
										 |  |  | 	String procedure_name = p_procedure_name; | 
					
						
							|  |  |  | 	godot_variant result = E->get()(native_handle, (godot_string *)&procedure_name, (godot_array *)&p_arguments); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	return *(Variant *)&result; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | void GDNative::call_native_raw(StringName p_raw_call_type, StringName p_procedure_name, void *data, int num_args, void **args, void *r_return) { | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 	Map<StringName, native_raw_call_cb>::Element *E = GDNativeCallRegistry::singleton->native_raw_calls.find(p_raw_call_type); | 
					
						
							|  |  |  | 	if (!E) { | 
					
						
							|  |  |  | 		ERR_PRINT((String("No handler for native raw call type \"" + p_raw_call_type) + "\" found").utf8().get_data()); | 
					
						
							|  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-07-14 01:44:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	String procedure_name = p_procedure_name; | 
					
						
							|  |  |  | 	E->get()(native_handle, (godot_string *)&procedure_name, data, num_args, args, r_return); | 
					
						
							| 
									
										
										
										
											2017-04-03 16:11:38 +02:00
										 |  |  | } |