diff options
Diffstat (limited to 'modules/gdnative')
37 files changed, 591 insertions, 346 deletions
diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub index 88588417d1..66b8d5cbdd 100644 --- a/modules/gdnative/SCsub +++ b/modules/gdnative/SCsub @@ -19,6 +19,20 @@ def _spaced(e): return e if e[-1] == '*' else e + ' ' def _build_gdnative_api_struct_header(api): + ext_wrappers = '' + + for name in api['extensions']: + ext_wrappers += ' extern const godot_gdnative_ext_' + name + '_api_struct *_gdnative_wrapper_' + name + '_api_struct;' + + ext_init = 'for (int i = 0; i < _gdnative_wrapper_api_struct->num_extensions; i++) { ' + ext_init += 'switch (_gdnative_wrapper_api_struct->extensions[i]->type) {' + + for name in api['extensions']: + ext_init += 'case GDNATIVE_EXT_' + api['extensions'][name]['type'] + ': ' + ext_init += '_gdnative_wrapper_' + name + '_api_struct = (' + 'godot_gdnative_ext_' + name + '_api_struct *) _gdnative_wrapper_api_struct->extensions[i]; break;' + + ext_init += '}' + out = [ '/* THIS FILE IS GENERATED DO NOT EDIT */', '#ifndef GODOT_GDNATIVE_API_STRUCT_H', @@ -29,7 +43,7 @@ def _build_gdnative_api_struct_header(api): '#include <nativescript/godot_nativescript.h>', '#include <pluginscript/godot_pluginscript.h>', '', - '#define GDNATIVE_API_INIT(options) do { extern const godot_gdnative_api_struct *_gdnative_wrapper_api_struct; _gdnative_wrapper_api_struct = options->api_struct; } while (0)', + '#define GDNATIVE_API_INIT(options) do { extern const godot_gdnative_api_struct *_gdnative_wrapper_api_struct;' + ext_wrappers + ' _gdnative_wrapper_api_struct = options->api_struct; ' + ext_init + ' } while (0)', '', '#ifdef __cplusplus', 'extern "C" {', @@ -40,11 +54,13 @@ def _build_gdnative_api_struct_header(api): '\tunsigned int minor;', '} godot_gdnative_api_version;', '', - 'typedef struct godot_gdnative_api_struct {', + 'typedef struct godot_gdnative_api_struct godot_gdnative_api_struct;', + '', + 'struct godot_gdnative_api_struct {', '\tunsigned int type;', '\tgodot_gdnative_api_version version;', '\tconst godot_gdnative_api_struct *next;', - '} godot_gdnative_api_struct;', + '};', '', 'enum GDNATIVE_API_TYPES {', '\tGDNATIVE_' + api['core']['type'] + ',' @@ -164,18 +180,23 @@ def _build_gdnative_wrapper_code(api): '#include <gdnative/gdnative.h>', '#include <nativescript/godot_nativescript.h>', '#include <pluginscript/godot_pluginscript.h>', + '#include <arvr/godot_arvr.h>', '', '#include <gdnative_api_struct.gen.h>', '', - 'godot_gdnative_api_struct *_gdnative_wrapper_api_struct = 0;', - '', '#ifdef __cplusplus', 'extern "C" {', '#endif', - '' + '', + 'godot_gdnative_core_api_struct *_gdnative_wrapper_api_struct = 0;', ] - for funcdef in api['api']: + for name in api['extensions']: + out.append('godot_gdnative_ext_' + name + '_api_struct *_gdnative_wrapper_' + name + '_api_struct;') + + out += [''] + + for funcdef in api['core']['api']: args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']]) out.append('%s%s(%s) {' % (_spaced(funcdef['return_type']), funcdef['name'], args)) @@ -188,6 +209,20 @@ def _build_gdnative_wrapper_code(api): out.append('}') out.append('') + for name in api['extensions']: + for funcdef in api['extensions'][name]['api']: + args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']]) + out.append('%s%s(%s) {' % (_spaced(funcdef['return_type']), funcdef['name'], args)) + + args = ', '.join(['%s' % n for t, n in funcdef['arguments']]) + + return_line = '\treturn ' if funcdef['return_type'] != 'void' else '\t' + return_line += '_gdnative_wrapper_' + name + '_api_struct->' + funcdef['name'] + '(' + args + ');' + + out.append(return_line) + out.append('}') + out.append('') + out += [ '#ifdef __cplusplus', '}', diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.cpp b/modules/gdnative/arvr/arvr_interface_gdnative.cpp index e2a7019fa4..02f2ee7424 100644 --- a/modules/gdnative/arvr/arvr_interface_gdnative.cpp +++ b/modules/gdnative/arvr/arvr_interface_gdnative.cpp @@ -166,11 +166,11 @@ void ARVRInterfaceGDNative::uninitialize() { interface->uninitialize(data); } -Size2 ARVRInterfaceGDNative::get_recommended_render_targetsize() { +Size2 ARVRInterfaceGDNative::get_render_targetsize() { ERR_FAIL_COND_V(interface == NULL, Size2()); - godot_vector2 result = interface->get_recommended_render_targetsize(data); + godot_vector2 result = interface->get_render_targetsize(data); Vector2 *vec = (Vector2 *)&result; return *vec; diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.h b/modules/gdnative/arvr/arvr_interface_gdnative.h index e45b51e070..96f7b580d5 100644 --- a/modules/gdnative/arvr/arvr_interface_gdnative.h +++ b/modules/gdnative/arvr/arvr_interface_gdnative.h @@ -68,7 +68,7 @@ public: virtual void set_anchor_detection_is_enabled(bool p_enable); /** rendering and internal **/ - virtual Size2 get_recommended_render_targetsize(); + virtual Size2 get_render_targetsize(); virtual bool is_stereo(); virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform); diff --git a/modules/gdnative/config.py b/modules/gdnative/config.py index df3556249d..68148c4d87 100644 --- a/modules/gdnative/config.py +++ b/modules/gdnative/config.py @@ -1,4 +1,3 @@ - def can_build(platform): return True @@ -6,7 +5,13 @@ def configure(env): env.use_ptrcall = True def get_doc_classes(): - return ["GDNative", "GDNativeLibrary", "NativeScript", "ARVRInterfaceGDNative"] + return [ + "ARVRInterfaceGDNative", + "GDNative", + "GDNativeLibrary", + "NativeScript", + "PluginScript", + ] def get_doc_path(): - return "doc_classes" + return "doc_classes" diff --git a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml index 308a7d5946..10957a3394 100644 --- a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml +++ b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" category="Core" version="3.0.alpha.custom_build"> +<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" category="Core" version="3.0-alpha"> <brief_description> GDNative wrapper for an ARVR interface </brief_description> diff --git a/modules/gdnative/doc_classes/GDNative.xml b/modules/gdnative/doc_classes/GDNative.xml index 83a1cf06f0..7a36d09aec 100644 --- a/modules/gdnative/doc_classes/GDNative.xml +++ b/modules/gdnative/doc_classes/GDNative.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDNative" inherits="Reference" category="Core" version="3.0.alpha.custom_build"> +<class name="GDNative" inherits="Reference" category="Core" version="3.0-alpha"> <brief_description> </brief_description> <description> diff --git a/modules/gdnative/doc_classes/GDNativeLibrary.xml b/modules/gdnative/doc_classes/GDNativeLibrary.xml index 361c89e6b3..e271665fd4 100644 --- a/modules/gdnative/doc_classes/GDNativeLibrary.xml +++ b/modules/gdnative/doc_classes/GDNativeLibrary.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.0.alpha.custom_build"> +<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.0-alpha"> <brief_description> </brief_description> <description> @@ -9,37 +9,51 @@ <demos> </demos> <methods> - <method name="get_active_library_path" qualifiers="const"> + <method name="get_config_file"> + <return type="ConfigFile"> + </return> + <description> + </description> + </method> + <method name="get_current_dependencies" qualifiers="const"> + <return type="PoolStringArray"> + </return> + <description> + </description> + </method> + <method name="get_current_library_path" qualifiers="const"> <return type="String"> </return> <description> </description> </method> - <method name="get_library_path" qualifiers="const"> + <method name="get_symbol_prefix" qualifiers="const"> <return type="String"> </return> - <argument index="0" name="platform" type="String"> - </argument> <description> </description> </method> - <method name="is_singleton_gdnative" qualifiers="const"> + <method name="is_current_library_statically_linked" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="is_singleton" qualifiers="const"> <return type="bool"> </return> <description> </description> </method> - <method name="set_library_path"> + <method name="set_load_once"> <return type="void"> </return> - <argument index="0" name="platform" type="String"> - </argument> - <argument index="1" name="path" type="String"> + <argument index="0" name="load_once" type="bool"> </argument> <description> </description> </method> - <method name="set_singleton_gdnative"> + <method name="set_singleton"> <return type="void"> </return> <argument index="0" name="singleton" type="bool"> @@ -47,9 +61,27 @@ <description> </description> </method> + <method name="set_symbol_prefix"> + <return type="void"> + </return> + <argument index="0" name="symbol_prefix" type="String"> + </argument> + <description> + </description> + </method> + <method name="should_load_once" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> </methods> <members> - <member name="singleton_gdnative" type="bool" setter="set_singleton_gdnative" getter="is_singleton_gdnative"> + <member name="load_once" type="bool" setter="set_load_once" getter="should_load_once"> + </member> + <member name="singleton" type="bool" setter="set_singleton" getter="is_singleton"> + </member> + <member name="symbol_prefix" type="String" setter="set_symbol_prefix" getter="get_symbol_prefix"> </member> </members> <constants> diff --git a/modules/gdnative/doc_classes/NativeScript.xml b/modules/gdnative/doc_classes/NativeScript.xml index b040cfd966..eb4e13f748 100644 --- a/modules/gdnative/doc_classes/NativeScript.xml +++ b/modules/gdnative/doc_classes/NativeScript.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NativeScript" inherits="Script" category="Core" version="3.0.alpha.custom_build"> +<class name="NativeScript" inherits="Script" category="Core" version="3.0-alpha"> <brief_description> </brief_description> <description> diff --git a/modules/gdnative/doc_classes/PluginScript.xml b/modules/gdnative/doc_classes/PluginScript.xml new file mode 100644 index 0000000000..a5ab422d3c --- /dev/null +++ b/modules/gdnative/doc_classes/PluginScript.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="PluginScript" inherits="Script" category="Core" version="3.0-alpha"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/modules/gdnative/gd_native_library_editor.cpp b/modules/gdnative/gd_native_library_editor.cpp index c37b7f473d..fda5dcdcad 100644 --- a/modules/gdnative/gd_native_library_editor.cpp +++ b/modules/gdnative/gd_native_library_editor.cpp @@ -44,7 +44,7 @@ void GDNativeLibraryEditor::_find_gdnative_singletons(EditorFileSystemDirectory } Ref<GDNativeLibrary> lib = ResourceLoader::load(p_dir->get_file_path(i)); - if (lib.is_valid() && lib->is_singleton_gdnative()) { + if (lib.is_valid() && lib->is_singleton()) { String path = p_dir->get_file_path(i); TreeItem *ti = libraries->create_item(libraries->get_root()); ti->set_text(0, path.get_file()); diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index 832a0cb859..44d6dffc85 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -37,161 +37,56 @@ #include "scene/main/scene_tree.h" -const String init_symbol = "godot_gdnative_init"; -const String terminate_symbol = "godot_gdnative_terminate"; +const String init_symbol = "gdnative_init"; +const String terminate_symbol = "gdnative_terminate"; +const String default_symbol_prefix = "godot_"; // Defined in gdnative_api_struct.gen.cpp extern const godot_gdnative_core_api_struct api_struct; -String GDNativeLibrary::platform_names[NUM_PLATFORMS + 1] = { - "X11_32bit", - "X11_64bit", - "Windows_32bit", - "Windows_64bit", - "OSX", - - "Android", - - "iOS_32bit", - "iOS_64bit", - - "WebAssembly", - - "" -}; -String GDNativeLibrary::platform_lib_ext[NUM_PLATFORMS + 1] = { - "so", - "so", - "dll", - "dll", - "dylib", - - "so", - - "dylib", - "dylib", - - "wasm", - - "" -}; - -GDNativeLibrary::Platform GDNativeLibrary::current_platform = -#if defined(X11_ENABLED) - (sizeof(void *) == 8 ? X11_64BIT : X11_32BIT); -#elif defined(WINDOWS_ENABLED) - (sizeof(void *) == 8 ? WINDOWS_64BIT : WINDOWS_32BIT); -#elif defined(OSX_ENABLED) - OSX; -#elif defined(IPHONE_ENABLED) - (sizeof(void *) == 8 ? IOS_64BIT : IOS_32BIT); -#elif defined(ANDROID_ENABLED) - ANDROID; -#elif defined(JAVASCRIPT_ENABLED) - WASM; -#else - NUM_PLATFORMS; -#endif - -GDNativeLibrary::GDNativeLibrary() - : library_paths(), singleton_gdnative(false) { -} +Map<String, Vector<Ref<GDNative> > > *GDNativeLibrary::loaded_libraries = NULL; -GDNativeLibrary::~GDNativeLibrary() { -} - -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); - ClassDB::bind_method(D_METHOD("get_active_library_path"), &GDNativeLibrary::get_active_library_path); +GDNativeLibrary::GDNativeLibrary() { + config_file.instance(); - ClassDB::bind_method(D_METHOD("is_singleton_gdnative"), &GDNativeLibrary::is_singleton_gdnative); - ClassDB::bind_method(D_METHOD("set_singleton_gdnative", "singleton"), &GDNativeLibrary::set_singleton_gdnative); + symbol_prefix = default_symbol_prefix; - ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "singleton_gdnative"), "set_singleton_gdnative", "is_singleton_gdnative"); -} - -bool GDNativeLibrary::_set(const StringName &p_name, const Variant &p_value) { - String name = p_name; - if (name.begins_with("platform/")) { - set_library_path(name.get_slice("/", 1), p_value); - return true; - } - return false; -} - -bool GDNativeLibrary::_get(const StringName &p_name, Variant &r_ret) const { - String name = p_name; - if (name.begins_with("platform/")) { - r_ret = get_library_path(name.get_slice("/", 1)); - return true; + if (GDNativeLibrary::loaded_libraries == NULL) { + GDNativeLibrary::loaded_libraries = memnew((Map<String, Vector<Ref<GDNative> > >)); } - return false; } -void GDNativeLibrary::_get_property_list(List<PropertyInfo> *p_list) const { - 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])); - } +GDNativeLibrary::~GDNativeLibrary() { } -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; - } - } - - if (i == NUM_PLATFORMS) { - ERR_EXPLAIN(String("No such platform: ") + p_platform); - ERR_FAIL(); - } +void GDNativeLibrary::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_config_file"), &GDNativeLibrary::get_config_file); - library_paths[i] = p_path; -} + 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); + ClassDB::bind_method(D_METHOD("is_current_library_statically_linked"), &GDNativeLibrary::is_current_library_statically_linked); -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; - } - } + 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); - if (i == NUM_PLATFORMS) { - ERR_EXPLAIN(String("No such platform: ") + p_platform); - ERR_FAIL_V(""); - } + 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); - return library_paths[i]; -} - -String GDNativeLibrary::get_active_library_path() const { - if (GDNativeLibrary::current_platform != NUM_PLATFORMS) { - return library_paths[GDNativeLibrary::current_platform]; - } - return ""; + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "load_once"), "set_load_once", "should_load_once"); + ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "singleton"), "set_singleton", "is_singleton"); + ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "symbol_prefix"), "set_symbol_prefix", "get_symbol_prefix"); } GDNative::GDNative() { native_handle = NULL; + initialized = false; } GDNative::~GDNative() { } -extern "C" void _api_anchor(); - -void GDNative::_compile_dummy_for_api() { - _api_anchor(); -} - void GDNative::_bind_methods() { ClassDB::bind_method(D_METHOD("set_library", "library"), &GDNative::set_library); ClassDB::bind_method(D_METHOD("get_library"), &GDNative::get_library); @@ -220,8 +115,8 @@ bool GDNative::initialize() { return false; } - String lib_path = library->get_active_library_path(); - if (lib_path.empty()) { + String lib_path = library->get_current_library_path(); + if (lib_path.empty() && !library->is_current_library_statically_linked()) { ERR_PRINT("No library set for this platform"); return false; } @@ -230,16 +125,34 @@ bool GDNative::initialize() { #else String path = ProjectSettings::get_singleton()->globalize_path(lib_path); #endif + + if (library->should_load_once()) { + if (GDNativeLibrary::loaded_libraries->has(lib_path)) { + // already loaded. Don't load again. + // copy some of the stuff instead + this->native_handle = (*GDNativeLibrary::loaded_libraries)[lib_path][0]->native_handle; + initialized = true; + return true; + } + } + Error err = OS::get_singleton()->open_dynamic_library(path, native_handle); - if (err != OK) { + if (err != OK && !library->is_current_library_statically_linked()) { return false; } void *library_init; - err = get_symbol(init_symbol, library_init); + + // we cheat here a little bit. you saw nothing + initialized = true; + + err = get_symbol(library->get_symbol_prefix() + init_symbol, library_init); + + initialized = false; if (err || !library_init) { - OS::get_singleton()->close_dynamic_library(native_handle); + if (!library->is_current_library_statically_linked()) + OS::get_singleton()->close_dynamic_library(native_handle); native_handle = NULL; ERR_PRINT("Failed to obtain godot_gdnative_init symbol"); return false; @@ -260,18 +173,42 @@ bool GDNative::initialize() { library_init_fpointer(&options); + initialized = true; + + if (library->should_load_once() && !GDNativeLibrary::loaded_libraries->has(lib_path)) { + Vector<Ref<GDNative> > gdnatives; + gdnatives.resize(1); + gdnatives[0] = Ref<GDNative>(this); + GDNativeLibrary::loaded_libraries->insert(lib_path, gdnatives); + } + return true; } bool GDNative::terminate() { - if (native_handle == NULL) { + if (!initialized) { ERR_PRINT("No valid library handle, can't terminate GDNative object"); return false; } + if (library->should_load_once()) { + Vector<Ref<GDNative> > *gdnatives = &(*GDNativeLibrary::loaded_libraries)[library->get_current_library_path()]; + if (gdnatives->size() > 1) { + // there are other GDNative's still using this library, so we actually don't terminte + gdnatives->erase(Ref<GDNative>(this)); + initialized = false; + return true; + } else if (gdnatives->size() == 1) { + // we're the last one, terminate! + gdnatives->clear(); + // wew this looks scary, but all it does is remove the entry completely + GDNativeLibrary::loaded_libraries->erase(GDNativeLibrary::loaded_libraries->find(library->get_current_library_path())); + } + } + void *library_terminate; - Error error = get_symbol(terminate_symbol, library_terminate); + Error error = get_symbol(library->get_symbol_prefix() + terminate_symbol, library_terminate); if (error || !library_terminate) { OS::get_singleton()->close_dynamic_library(native_handle); native_handle = NULL; @@ -281,13 +218,13 @@ bool GDNative::terminate() { godot_gdnative_terminate_fn library_terminate_pointer; library_terminate_pointer = (godot_gdnative_terminate_fn)library_terminate; - // TODO(karroffel): remove this? Should be part of NativeScript, not - // GDNative IMO godot_gdnative_terminate_options options; options.in_editor = Engine::get_singleton()->is_editor_hint(); library_terminate_pointer(&options); + initialized = false; + // GDNativeScriptLanguage::get_singleton()->initialized_libraries.erase(p_native_lib->path); OS::get_singleton()->close_dynamic_library(native_handle); @@ -297,7 +234,7 @@ bool GDNative::terminate() { } bool GDNative::is_initialized() { - return (native_handle != NULL); + return initialized; } void GDNativeCallRegistry::register_native_call_type(StringName p_call_type, native_call_cb p_callback) { @@ -342,7 +279,7 @@ Variant GDNative::call_native(StringName p_native_call_type, StringName p_proced Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle) { - if (native_handle == NULL) { + if (!initialized) { ERR_PRINT("No valid library handle, can't get symbol from GDNative object"); return ERR_CANT_OPEN; } @@ -355,3 +292,159 @@ Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle) { return result; } + +RES GDNativeLibraryResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error) { + Ref<GDNativeLibrary> lib; + lib.instance(); + + Ref<ConfigFile> config = lib->get_config_file(); + + Error err = config->load(p_path); + + if (r_error) { + *r_error = err; + } + + lib->set_singleton(config->get_value("general", "singleton", false)); + lib->set_load_once(config->get_value("general", "load_once", true)); + lib->set_symbol_prefix(config->get_value("general", "symbol_prefix", default_symbol_prefix)); + + String entry_lib_path; + { + + List<String> entry_keys; + config->get_section_keys("entry", &entry_keys); + + 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 = config->get_value("entry", key); + break; + } + } + + Vector<String> dependency_paths; + { + + List<String> dependency_keys; + config->get_section_keys("dependencies", &dependency_keys); + + 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 = config->get_value("dependencies", key); + break; + } + } + + bool is_statically_linked = false; + { + + List<String> static_linking_keys; + config->get_section_keys("static_linking", &static_linking_keys); + + for (List<String>::Element *E = static_linking_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; + } + + is_statically_linked = config->get_value("static_linking", key); + break; + } + } + + lib->current_library_path = entry_lib_path; + lib->current_dependencies = dependency_paths; + lib->current_library_statically_linked = is_statically_linked; + + 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 { + return p_type == "GDNativeLibrary"; +} + +String GDNativeLibraryResourceLoader::get_resource_type(const String &p_path) const { + String el = p_path.get_extension().to_lower(); + if (el == "gdnlib") + return "GDNativeLibrary"; + 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()); + + return config->save(p_path); +} + +bool GDNativeLibraryResourceSaver::recognize(const RES &p_resource) const { + return Object::cast_to<GDNativeLibrary>(*p_resource) != NULL; +} + +void GDNativeLibraryResourceSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { + if (Object::cast_to<GDNativeLibrary>(*p_resource) != NULL) { + p_extensions->push_back("gdnlib"); + } +} diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h index e44cc55a79..061dff9267 100644 --- a/modules/gdnative/gdnative.h +++ b/modules/gdnative/gdnative.h @@ -38,66 +38,69 @@ #include "gdnative/gdnative.h" #include "gdnative_api_struct.gen.h" -class GDNativeLibrary : public Resource { - GDCLASS(GDNativeLibrary, Resource) - - enum Platform { - X11_32BIT, - X11_64BIT, - WINDOWS_32BIT, - WINDOWS_64BIT, - // NOTE(karroffel): I heard OSX 32 bit is dead, so 64 only - OSX, - - // Android .so files must be located in directories corresponding to Android ABI names: - // https://developer.android.com/ndk/guides/abis.html - // Android runtime will select the matching library depending on the device. - // The value here must simply point to the .so name, for example: - // "res://libmy_gdnative.so" or "libmy_gdnative.so", - // while in the project the actual paths can be "lib/android/armeabi-v7a/libmy_gdnative.so", - // "lib/android/arm64-v8a/libmy_gdnative.so". - ANDROID, - - IOS_32BIT, - IOS_64BIT, - - // TODO(karroffel): figure out how to deal with web stuff at all... - WASM, - - // TODO(karroffel): does UWP have different libs?? - // UWP, +#include "io/config_file.h" - NUM_PLATFORMS +class GDNativeLibraryResourceLoader; +class GDNative; - }; +class GDNativeLibrary : public Resource { + GDCLASS(GDNativeLibrary, Resource) - static String platform_names[NUM_PLATFORMS + 1]; - static String platform_lib_ext[NUM_PLATFORMS + 1]; + static Map<String, Vector<Ref<GDNative> > > *loaded_libraries; - static Platform current_platform; + friend class GDNativeLibraryResourceLoader; + friend class GDNative; - String library_paths[NUM_PLATFORMS]; + Ref<ConfigFile> config_file; - bool singleton_gdnative; + String current_library_path; + Vector<String> current_dependencies; + bool current_library_statically_linked; -protected: - bool _set(const StringName &p_name, const Variant &p_value); - bool _get(const StringName &p_name, Variant &r_ret) const; - void _get_property_list(List<PropertyInfo> *p_list) const; + bool singleton; + bool load_once; + String symbol_prefix; public: GDNativeLibrary(); ~GDNativeLibrary(); - static void _bind_methods(); + _FORCE_INLINE_ Ref<ConfigFile> get_config_file() { return config_file; } + + // things that change per-platform + // so there are no setters for this + _FORCE_INLINE_ String get_current_library_path() const { + return current_library_path; + } + _FORCE_INLINE_ Vector<String> get_current_dependencies() const { + return current_dependencies; + } + _FORCE_INLINE_ bool is_current_library_statically_linked() const { + return current_library_statically_linked; + } - void set_library_path(StringName p_platform, String p_path); - String get_library_path(StringName p_platform) const; + // things that are a property of the library itself, not platform specific + _FORCE_INLINE_ bool should_load_once() const { + return load_once; + } + _FORCE_INLINE_ bool is_singleton() const { + return singleton; + } + _FORCE_INLINE_ String get_symbol_prefix() const { + return symbol_prefix; + } - String get_active_library_path() const; + _FORCE_INLINE_ void set_load_once(bool p_load_once) { + load_once = p_load_once; + } + _FORCE_INLINE_ void set_singleton(bool p_singleton) { + singleton = p_singleton; + } + _FORCE_INLINE_ void set_symbol_prefix(String p_symbol_prefix) { + symbol_prefix = p_symbol_prefix; + } - _FORCE_INLINE_ bool is_singleton_gdnative() const { return singleton_gdnative; } - _FORCE_INLINE_ void set_singleton_gdnative(bool p_singleton) { singleton_gdnative = p_singleton; } + static void _bind_methods(); }; typedef godot_variant (*native_call_cb)(void *, godot_array *); @@ -124,10 +127,9 @@ class GDNative : public Reference { Ref<GDNativeLibrary> library; - // TODO(karroffel): different platforms? WASM???? void *native_handle; - void _compile_dummy_for_api(); + bool initialized; public: GDNative(); @@ -148,4 +150,19 @@ public: Error get_symbol(StringName p_procedure_name, void *&r_handle); }; +class GDNativeLibraryResourceLoader : public ResourceFormatLoader { +public: + virtual RES load(const String &p_path, const String &p_original_path, Error *r_error); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + +class GDNativeLibraryResourceSaver : public ResourceFormatSaver { +public: + virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags); + virtual bool recognize(const RES &p_resource) const; + virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const; +}; + #endif // GDNATIVE_H diff --git a/modules/gdnative/gdnative/array.cpp b/modules/gdnative/gdnative/array.cpp index 90bc4dc031..e0d9514985 100644 --- a/modules/gdnative/gdnative/array.cpp +++ b/modules/gdnative/gdnative/array.cpp @@ -41,9 +41,6 @@ extern "C" { #endif -void _array_api_anchor() { -} - void GDAPI godot_array_new(godot_array *r_dest) { Array *dest = (Array *)r_dest; memnew_placement(dest, Array); diff --git a/modules/gdnative/gdnative/basis.cpp b/modules/gdnative/gdnative/basis.cpp index 28af93f942..39ca754dc7 100644 --- a/modules/gdnative/gdnative/basis.cpp +++ b/modules/gdnative/gdnative/basis.cpp @@ -36,8 +36,6 @@ extern "C" { #endif -void _basis_api_anchor() {} - void GDAPI godot_basis_new_with_rows(godot_basis *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis) { const Vector3 *x_axis = (const Vector3 *)p_x_axis; const Vector3 *y_axis = (const Vector3 *)p_y_axis; diff --git a/modules/gdnative/gdnative/color.cpp b/modules/gdnative/gdnative/color.cpp index 2a5c0887a1..281a4c416f 100644 --- a/modules/gdnative/gdnative/color.cpp +++ b/modules/gdnative/gdnative/color.cpp @@ -36,8 +36,6 @@ extern "C" { #endif -void _color_api_anchor() {} - void GDAPI godot_color_new_rgba(godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b, const godot_real p_a) { Color *dest = (Color *)r_dest; diff --git a/modules/gdnative/gdnative/dictionary.cpp b/modules/gdnative/gdnative/dictionary.cpp index 7f8320622d..8363416946 100644 --- a/modules/gdnative/gdnative/dictionary.cpp +++ b/modules/gdnative/gdnative/dictionary.cpp @@ -38,8 +38,6 @@ extern "C" { #endif -void _dictionary_api_anchor() {} - void GDAPI godot_dictionary_new(godot_dictionary *r_dest) { Dictionary *dest = (Dictionary *)r_dest; memnew_placement(dest, Dictionary); diff --git a/modules/gdnative/gdnative/gdnative.cpp b/modules/gdnative/gdnative/gdnative.cpp index 64a7c33cf8..6dfa7ec20b 100644 --- a/modules/gdnative/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative/gdnative.cpp @@ -30,57 +30,16 @@ #include "gdnative/gdnative.h" #include "class_db.h" +#include "engine.h" #include "error_macros.h" #include "global_constants.h" #include "os/os.h" -#include "project_settings.h" #include "variant.h" #ifdef __cplusplus extern "C" { #endif -extern "C" void _string_api_anchor(); -extern "C" void _string_name_api_anchor(); -extern "C" void _vector2_api_anchor(); -extern "C" void _rect2_api_anchor(); -extern "C" void _vector3_api_anchor(); -extern "C" void _transform2d_api_anchor(); -extern "C" void _plane_api_anchor(); -extern "C" void _quat_api_anchor(); -extern "C" void _basis_api_anchor(); -extern "C" void _rect3_api_anchor(); -extern "C" void _transform_api_anchor(); -extern "C" void _color_api_anchor(); -extern "C" void _node_path_api_anchor(); -extern "C" void _rid_api_anchor(); -extern "C" void _dictionary_api_anchor(); -extern "C" void _array_api_anchor(); -extern "C" void _pool_arrays_api_anchor(); -extern "C" void _variant_api_anchor(); - -void _api_anchor() { - - _string_api_anchor(); - _string_name_api_anchor(); - _vector2_api_anchor(); - _rect2_api_anchor(); - _vector3_api_anchor(); - _transform2d_api_anchor(); - _plane_api_anchor(); - _quat_api_anchor(); - _rect3_api_anchor(); - _basis_api_anchor(); - _transform_api_anchor(); - _color_api_anchor(); - _node_path_api_anchor(); - _rid_api_anchor(); - _dictionary_api_anchor(); - _array_api_anchor(); - _pool_arrays_api_anchor(); - _variant_api_anchor(); -} - void GDAPI godot_object_destroy(godot_object *p_o) { memdelete((Object *)p_o); } @@ -88,7 +47,7 @@ void GDAPI godot_object_destroy(godot_object *p_o) { // Singleton API godot_object GDAPI *godot_global_get_singleton(char *p_name) { - return (godot_object *)ProjectSettings::get_singleton()->get_singleton_object(String(p_name)); + return (godot_object *)Engine::get_singleton()->get_singleton_object(String(p_name)); } // result shouldn't be freed void GDAPI *godot_get_stack_bottom() { @@ -133,14 +92,6 @@ godot_variant GDAPI godot_method_bind_call(godot_method_bind *p_method_bind, god return ret; } -// @Todo -/* -void GDAPI godot_method_bind_varcall(godot_method_bind *p_method_bind) -{ - -} -*/ - godot_class_constructor GDAPI godot_get_class_constructor(const char *p_classname) { ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(StringName(p_classname)); if (class_info) diff --git a/modules/gdnative/gdnative/node_path.cpp b/modules/gdnative/gdnative/node_path.cpp index 50fade5b94..2bd278e050 100644 --- a/modules/gdnative/gdnative/node_path.cpp +++ b/modules/gdnative/gdnative/node_path.cpp @@ -36,8 +36,6 @@ extern "C" { #endif -void _node_path_api_anchor() {} - void GDAPI godot_node_path_new(godot_node_path *r_dest, const godot_string *p_from) { NodePath *dest = (NodePath *)r_dest; const String *from = (const String *)p_from; diff --git a/modules/gdnative/gdnative/plane.cpp b/modules/gdnative/gdnative/plane.cpp index a5e05ffa6b..c92efb8d99 100644 --- a/modules/gdnative/gdnative/plane.cpp +++ b/modules/gdnative/gdnative/plane.cpp @@ -36,8 +36,6 @@ extern "C" { #endif -void _plane_api_anchor() {} - void GDAPI godot_plane_new_with_reals(godot_plane *r_dest, const godot_real p_a, const godot_real p_b, const godot_real p_c, const godot_real p_d) { Plane *dest = (Plane *)r_dest; diff --git a/modules/gdnative/gdnative/pool_arrays.cpp b/modules/gdnative/gdnative/pool_arrays.cpp index 731e930908..562cc344a9 100644 --- a/modules/gdnative/gdnative/pool_arrays.cpp +++ b/modules/gdnative/gdnative/pool_arrays.cpp @@ -41,9 +41,6 @@ extern "C" { #endif -void _pool_arrays_api_anchor() { -} - #define memnew_placement_custom(m_placement, m_class, m_constr) _post_initialize(new (m_placement, sizeof(m_class), "") m_constr) // byte diff --git a/modules/gdnative/gdnative/quat.cpp b/modules/gdnative/gdnative/quat.cpp index 7db7847da1..2d012c069f 100644 --- a/modules/gdnative/gdnative/quat.cpp +++ b/modules/gdnative/gdnative/quat.cpp @@ -36,8 +36,6 @@ extern "C" { #endif -void _quat_api_anchor() {} - void GDAPI godot_quat_new(godot_quat *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z, const godot_real p_w) { Quat *dest = (Quat *)r_dest; diff --git a/modules/gdnative/gdnative/rect2.cpp b/modules/gdnative/gdnative/rect2.cpp index ecd8cce9ca..b0b0e28138 100644 --- a/modules/gdnative/gdnative/rect2.cpp +++ b/modules/gdnative/gdnative/rect2.cpp @@ -36,8 +36,6 @@ extern "C" { #endif -void _rect2_api_anchor() {} - void GDAPI godot_rect2_new_with_position_and_size(godot_rect2 *r_dest, const godot_vector2 *p_pos, const godot_vector2 *p_size) { const Vector2 *position = (const Vector2 *)p_pos; const Vector2 *size = (const Vector2 *)p_size; diff --git a/modules/gdnative/gdnative/rect3.cpp b/modules/gdnative/gdnative/rect3.cpp index d34d964db9..8e088743b4 100644 --- a/modules/gdnative/gdnative/rect3.cpp +++ b/modules/gdnative/gdnative/rect3.cpp @@ -36,8 +36,6 @@ extern "C" { #endif -void _rect3_api_anchor() {} - void GDAPI godot_rect3_new(godot_rect3 *r_dest, const godot_vector3 *p_pos, const godot_vector3 *p_size) { const Vector3 *pos = (const Vector3 *)p_pos; const Vector3 *size = (const Vector3 *)p_size; diff --git a/modules/gdnative/gdnative/rid.cpp b/modules/gdnative/gdnative/rid.cpp index f05c39906c..c6e8d82494 100644 --- a/modules/gdnative/gdnative/rid.cpp +++ b/modules/gdnative/gdnative/rid.cpp @@ -37,8 +37,6 @@ extern "C" { #endif -void _rid_api_anchor() {} - void GDAPI godot_rid_new(godot_rid *r_dest) { RID *dest = (RID *)r_dest; memnew_placement(dest, RID); diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp index 619003083d..781b8754bd 100644 --- a/modules/gdnative/gdnative/string.cpp +++ b/modules/gdnative/gdnative/string.cpp @@ -39,9 +39,6 @@ extern "C" { #endif -void _string_api_anchor() { -} - void GDAPI godot_string_new(godot_string *r_dest) { String *dest = (String *)r_dest; memnew_placement(dest, String); diff --git a/modules/gdnative/gdnative/string_name.cpp b/modules/gdnative/gdnative/string_name.cpp index 5c00fdfc2f..5c79e0acbd 100644 --- a/modules/gdnative/gdnative/string_name.cpp +++ b/modules/gdnative/gdnative/string_name.cpp @@ -38,9 +38,6 @@ extern "C" { #endif -void _string_name_api_anchor() { -} - void GDAPI godot_string_name_new(godot_string_name *r_dest, const godot_string *p_name) { StringName *dest = (StringName *)r_dest; const String *name = (const String *)p_name; diff --git a/modules/gdnative/gdnative/transform.cpp b/modules/gdnative/gdnative/transform.cpp index d7a3e78d3f..96b2ec8a7a 100644 --- a/modules/gdnative/gdnative/transform.cpp +++ b/modules/gdnative/gdnative/transform.cpp @@ -36,8 +36,6 @@ extern "C" { #endif -void _transform_api_anchor() {} - void GDAPI godot_transform_new_with_axis_origin(godot_transform *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis, const godot_vector3 *p_origin) { const Vector3 *x_axis = (const Vector3 *)p_x_axis; const Vector3 *y_axis = (const Vector3 *)p_y_axis; diff --git a/modules/gdnative/gdnative/transform2d.cpp b/modules/gdnative/gdnative/transform2d.cpp index dcb54f7a53..0a6334516b 100644 --- a/modules/gdnative/gdnative/transform2d.cpp +++ b/modules/gdnative/gdnative/transform2d.cpp @@ -36,8 +36,6 @@ extern "C" { #endif -void _transform2d_api_anchor() {} - void GDAPI godot_transform2d_new(godot_transform2d *r_dest, const godot_real p_rot, const godot_vector2 *p_pos) { const Vector2 *pos = (const Vector2 *)p_pos; Transform2D *dest = (Transform2D *)r_dest; diff --git a/modules/gdnative/gdnative/variant.cpp b/modules/gdnative/gdnative/variant.cpp index 9ba4166c1d..0c31bc643c 100644 --- a/modules/gdnative/gdnative/variant.cpp +++ b/modules/gdnative/gdnative/variant.cpp @@ -36,8 +36,6 @@ extern "C" { #endif -void _variant_api_anchor() {} - #define memnew_placement_custom(m_placement, m_class, m_constr) _post_initialize(new (m_placement, sizeof(m_class), "") m_constr) // Constructors diff --git a/modules/gdnative/gdnative/vector2.cpp b/modules/gdnative/gdnative/vector2.cpp index 67f858997f..7a5b29e0c4 100644 --- a/modules/gdnative/gdnative/vector2.cpp +++ b/modules/gdnative/gdnative/vector2.cpp @@ -36,8 +36,6 @@ extern "C" { #endif -void _vector2_api_anchor() {} - void GDAPI godot_vector2_new(godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y) { Vector2 *dest = (Vector2 *)r_dest; diff --git a/modules/gdnative/gdnative/vector3.cpp b/modules/gdnative/gdnative/vector3.cpp index c85a3f1c08..11ffb3320b 100644 --- a/modules/gdnative/gdnative/vector3.cpp +++ b/modules/gdnative/gdnative/vector3.cpp @@ -36,8 +36,6 @@ extern "C" { #endif -void _vector3_api_anchor() {} - void GDAPI godot_vector3_new(godot_vector3 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z) { Vector3 *dest = (Vector3 *)r_dest; diff --git a/modules/gdnative/include/arvr/godot_arvr.h b/modules/gdnative/include/arvr/godot_arvr.h index c12251439d..be13ac954b 100644 --- a/modules/gdnative/include/arvr/godot_arvr.h +++ b/modules/gdnative/include/arvr/godot_arvr.h @@ -47,7 +47,7 @@ typedef struct { godot_bool (*is_initialized)(const void *); godot_bool (*initialize)(void *); void (*uninitialize)(void *); - godot_vector2 (*get_recommended_render_targetsize)(const void *); + godot_vector2 (*get_render_targetsize)(const void *); godot_transform (*get_transform_for_eye)(void *, godot_int, godot_transform *); void (*fill_projection_for_eye)(void *, godot_real *, godot_int, godot_real, godot_real, godot_real); void (*commit_for_eye)(void *, godot_int, godot_rid *, godot_rect2 *); diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h index 8fa96fd3af..a479eced16 100644 --- a/modules/gdnative/include/gdnative/gdnative.h +++ b/modules/gdnative/include/gdnative/gdnative.h @@ -53,7 +53,7 @@ extern "C" { // This is for libraries *using* the header, NOT GODOT EXPOSING STUFF!! #ifdef _WIN32 -#define GDN_EXPORT __declspec(dllexport) +#define GDN_EXPORT #else #define GDN_EXPORT #endif diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp index 63fb71feb6..f9d699fb59 100644 --- a/modules/gdnative/nativescript/api_generator.cpp +++ b/modules/gdnative/nativescript/api_generator.cpp @@ -32,9 +32,9 @@ #ifdef TOOLS_ENABLED #include "core/class_db.h" +#include "core/engine.h" #include "core/global_constants.h" #include "core/pair.h" -#include "core/project_settings.h" #include "os/file_access.h" // helper stuff @@ -177,7 +177,7 @@ List<ClassAPI> generate_c_api_classes() { if (name.begins_with("_")) { name.remove(0); } - class_api.is_singleton = ProjectSettings::get_singleton()->has_singleton(name); + class_api.is_singleton = Engine::get_singleton()->has_singleton(name); } class_api.is_instanciable = !class_api.is_singleton && ClassDB::can_instance(class_name); diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index c1df7def2e..c2c7c27f25 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -40,6 +40,8 @@ #include "scene/main/scene_tree.h" #include "scene/resources/scene_format_text.h" +#include <stdlib.h> + #ifndef NO_THREADS #include "os/thread.h" #endif @@ -52,7 +54,11 @@ #include "editor/editor_node.h" #endif -////// Script stuff +// +// +// Script stuff +// +// void NativeScript::_bind_methods() { ClassDB::bind_method(D_METHOD("set_class_name", "class_name"), &NativeScript::set_class_name); @@ -108,7 +114,7 @@ void NativeScript::set_library(Ref<GDNativeLibrary> p_library) { return; } library = p_library; - lib_path = library->get_active_library_path(); + lib_path = library->get_current_library_path(); #ifndef NO_THREADS if (Thread::get_caller_id() != Thread::get_main_id()) { @@ -414,7 +420,6 @@ Variant NativeScript::_new(const Variant **p_args, int p_argcount, Variant::Call } } -// TODO(karroffel): implement this NativeScript::NativeScript() { library = Ref<GDNative>(); lib_path = ""; @@ -424,7 +429,6 @@ NativeScript::NativeScript() { #endif } -// TODO(karroffel): implement this NativeScript::~NativeScript() { NSL->unregister_script(this); @@ -433,7 +437,11 @@ NativeScript::~NativeScript() { #endif } -////// ScriptInstance stuff +// +// +// ScriptInstance stuff +// +// #define GET_SCRIPT_DESC() script->get_script_desc() @@ -691,7 +699,6 @@ NativeScriptInstance::RPCMode NativeScriptInstance::get_rpc_mode(const StringNam return RPC_MODE_DISABLED; } -// TODO(karroffel): implement this NativeScriptInstance::RPCMode NativeScriptInstance::get_rset_mode(const StringName &p_variable) const { NativeScriptDesc *script_data = GET_SCRIPT_DESC(); @@ -774,15 +781,14 @@ NativeScriptInstance::~NativeScriptInstance() { } } -////// ScriptingLanguage stuff +// +// +// ScriptingLanguage stuff +// +// NativeScriptLanguage *NativeScriptLanguage::singleton; -extern "C" void _native_script_hook(); -void NativeScriptLanguage::_hacky_api_anchor() { - _native_script_hook(); -} - void NativeScriptLanguage::_unload_stuff() { for (Map<String, Map<StringName, NativeScriptDesc> >::Element *L = library_classes.front(); L; L = L->next()) { for (Map<StringName, NativeScriptDesc>::Element *C = L->get().front(); C; C = C->next()) { @@ -819,9 +825,7 @@ NativeScriptLanguage::NativeScriptLanguage() { #endif } -// TODO(karroffel): implement this NativeScriptLanguage::~NativeScriptLanguage() { - // _unload_stuff(); // NOTE(karroffel): This gets called in ::finish() for (Map<String, Ref<GDNative> >::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) { @@ -847,7 +851,6 @@ void _add_reload_node() { #endif } -// TODO(karroffel): implement this void NativeScriptLanguage::init() { #if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) @@ -860,6 +863,7 @@ void NativeScriptLanguage::init() { if (generate_c_api(E->next()->get()) != OK) { ERR_PRINT("Failed to generate C API\n"); } + exit(0); } #endif @@ -886,11 +890,9 @@ void NativeScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) co void NativeScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const { } -// TODO(karroffel): implement this Ref<Script> NativeScriptLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const { NativeScript *s = memnew(NativeScript); s->set_class_name(p_class_name); - // TODO(karroffel): use p_base_class_name return Ref<NativeScript>(s); } bool NativeScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const { @@ -988,7 +990,7 @@ void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) { MutexLock lock(mutex); #endif // See if this library was "registered" already. - const String &lib_path = lib->get_active_library_path(); + const String &lib_path = lib->get_current_library_path(); ERR_EXPLAIN(lib->get_name() + " does not have a library for the current platform"); ERR_FAIL_COND(lib_path.length() == 0); Map<String, Ref<GDNative> >::Element *E = library_gdnatives.find(lib_path); @@ -998,7 +1000,7 @@ void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) { gdn.instance(); gdn->set_library(lib); - // TODO(karroffel): check the return value? + // TODO check the return value? gdn->initialize(); library_gdnatives.insert(lib_path, gdn); @@ -1010,7 +1012,7 @@ void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) { void *proc_ptr; - Error err = gdn->get_symbol(_init_call_name, proc_ptr); + Error err = gdn->get_symbol(lib->get_symbol_prefix() + _init_call_name, proc_ptr); if (err != OK) { ERR_PRINT(String("No " + _init_call_name + " in \"" + lib_path + "\" found").utf8().get_data()); @@ -1051,7 +1053,7 @@ void NativeScriptLanguage::call_libraries_cb(const StringName &name) { if (L->get()->is_initialized()) { void *proc_ptr; - Error err = L->get()->get_symbol(name, proc_ptr); + Error err = L->get()->get_symbol(L->get()->get_library()->get_symbol_prefix() + name, proc_ptr); if (!err) { ((void (*)())proc_ptr)(); @@ -1140,7 +1142,7 @@ void NativeReloadNode::_notification(int p_what) { // here the library registers all the classes and stuff. void *proc_ptr; - Error err = L->get()->get_symbol("godot_nativescript_init", proc_ptr); + Error err = L->get()->get_symbol(L->get()->get_library()->get_symbol_prefix() + "nativescript_init", proc_ptr); if (err != OK) { ERR_PRINT(String("No godot_nativescript_init in \"" + L->key() + "\" found").utf8().get_data()); } else { diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h index e8fc9e6880..f0f14e2f30 100644 --- a/modules/gdnative/nativescript/nativescript.h +++ b/modules/gdnative/nativescript/nativescript.h @@ -229,15 +229,15 @@ public: Map<String, Set<NativeScript *> > library_script_users; const StringName _init_call_type = "nativescript_init"; - const StringName _init_call_name = "godot_nativescript_init"; + const StringName _init_call_name = "nativescript_init"; const StringName _noarg_call_type = "nativescript_no_arg"; - const StringName _frame_call_name = "godot_nativescript_frame"; + const StringName _frame_call_name = "nativescript_frame"; #ifndef NO_THREADS - const StringName _thread_enter_call_name = "godot_nativescript_thread_enter"; - const StringName _thread_exit_call_name = "godot_nativescript_thread_exit"; + const StringName _thread_enter_call_name = "nativescript_thread_enter"; + const StringName _thread_exit_call_name = "nativescript_thread_exit"; #endif NativeScriptLanguage(); diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 19a62b9c4f..29b0a6719c 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -48,7 +48,7 @@ #include "gd_native_library_editor.h" // Class used to discover singleton gdnative files -void actual_discoverer_handler(); +static void actual_discoverer_handler(); class GDNativeSingletonDiscover : public Object { // GDCLASS(GDNativeSingletonDiscover, Object) @@ -66,7 +66,7 @@ class GDNativeSingletonDiscover : public Object { } }; -Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) { +static Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) { Set<String> file_paths; @@ -81,7 +81,7 @@ Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) { } Ref<GDNativeLibrary> lib = ResourceLoader::load(p_dir->get_file_path(i)); - if (lib.is_valid() && lib->is_singleton_gdnative()) { + if (lib.is_valid() && lib->is_singleton()) { file_paths.insert(p_dir->get_file_path(i)); } } @@ -98,7 +98,7 @@ Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) { return file_paths; } -void actual_discoverer_handler() { +static void actual_discoverer_handler() { EditorFileSystemDirectory *dir = EditorFileSystem::get_singleton()->get_filesystem(); Set<String> file_paths = get_gdnative_singletons(dir); @@ -115,7 +115,125 @@ void actual_discoverer_handler() { ProjectSettings::get_singleton()->save(); } -GDNativeSingletonDiscover *discoverer = NULL; +static GDNativeSingletonDiscover *discoverer = NULL; + +class GDNativeExportPlugin : public EditorExportPlugin { + +protected: + virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features); +}; + +void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) { + if (p_type != "GDNativeLibrary") { + return; + } + + Ref<GDNativeLibrary> lib = ResourceLoader::load(p_path); + + if (lib.is_null()) { + return; + } + + Ref<ConfigFile> config = lib->get_config_file(); + + String entry_lib_path; + { + + List<String> entry_keys; + config->get_section_keys("entry", &entry_keys); + + 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 = p_features.has(tags[i]); + + if (!has_feature) { + skip = true; + break; + } + } + + if (skip) { + continue; + } + + entry_lib_path = config->get_value("entry", key); + break; + } + } + + Vector<String> dependency_paths; + { + + List<String> dependency_keys; + config->get_section_keys("dependencies", &dependency_keys); + + 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 = p_features.has(tags[i]); + + if (!has_feature) { + skip = true; + break; + } + } + + if (skip) { + continue; + } + + dependency_paths = config->get_value("dependencies", key); + break; + } + } + + bool is_statically_linked = false; + { + + List<String> static_linking_keys; + config->get_section_keys("static_linking", &static_linking_keys); + + for (List<String>::Element *E = static_linking_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 = p_features.has(tags[i]); + + if (!has_feature) { + skip = true; + break; + } + } + + if (skip) { + continue; + } + + is_statically_linked = config->get_value("static_linking", key); + break; + } + } + + if (!is_statically_linked) + add_shared_object(entry_lib_path); + + for (int i = 0; i < dependency_paths.size(); i++) { + add_shared_object(dependency_paths[i]); + } +} static void editor_init_callback() { @@ -125,11 +243,16 @@ static void editor_init_callback() { discoverer = memnew(GDNativeSingletonDiscover); EditorFileSystem::get_singleton()->connect("filesystem_changed", discoverer, "get_class"); + + Ref<GDNativeExportPlugin> export_plugin; + export_plugin.instance(); + + EditorExport::get_singleton()->add_export_plugin(export_plugin); } #endif -godot_variant cb_standard_varcall(void *p_procedure_handle, godot_array *p_args) { +static godot_variant cb_standard_varcall(void *p_procedure_handle, godot_array *p_args) { godot_gdnative_procedure_fn proc; proc = (godot_gdnative_procedure_fn)p_procedure_handle; @@ -141,6 +264,9 @@ GDNativeCallRegistry *GDNativeCallRegistry::singleton; Vector<Ref<GDNative> > singleton_gdnatives; +GDNativeLibraryResourceLoader *resource_loader_gdnlib = NULL; +GDNativeLibraryResourceSaver *resource_saver_gdnlib = NULL; + void register_gdnative_types() { #ifdef TOOLS_ENABLED @@ -153,6 +279,12 @@ void register_gdnative_types() { ClassDB::register_class<GDNativeLibrary>(); ClassDB::register_class<GDNative>(); + resource_loader_gdnlib = memnew(GDNativeLibraryResourceLoader); + resource_saver_gdnlib = memnew(GDNativeLibraryResourceSaver); + + ResourceLoader::add_resource_format_loader(resource_loader_gdnlib); + ResourceSaver::add_resource_format_saver(resource_saver_gdnlib); + GDNativeCallRegistry::singleton = memnew(GDNativeCallRegistry); GDNativeCallRegistry::singleton->register_native_call_type("standard_varcall", cb_standard_varcall); @@ -185,11 +317,11 @@ void register_gdnative_types() { void *proc_ptr; Error err = singleton_gdnatives[i]->get_symbol( - "godot_gdnative_singleton", + lib->get_symbol_prefix() + "gdnative_singleton", proc_ptr); if (err != OK) { - ERR_PRINT((String("No godot_gdnative_singleton in \"" + singleton_gdnatives[i]->get_library()->get_active_library_path()) + "\" found").utf8().get_data()); + ERR_PRINT((String("No godot_gdnative_singleton in \"" + singleton_gdnatives[i]->get_library()->get_current_library_path()) + "\" found").utf8().get_data()); } else { ((void (*)())proc_ptr)(); } @@ -224,6 +356,9 @@ void unregister_gdnative_types() { } #endif + memdelete(resource_loader_gdnlib); + memdelete(resource_saver_gdnlib); + // This is for printing out the sizes of the core types /* |