Merge pull request #60601 from touilleMan/gdextension_get_library_path
Add GDNativeInterface::get_library_path to GDExtension
This commit is contained in:
commit
c9ce4069a3
19 changed files with 65 additions and 17 deletions
|
@ -1069,4 +1069,6 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
|
||||||
gdni.classdb_register_extension_class_property_subgroup = nullptr;
|
gdni.classdb_register_extension_class_property_subgroup = nullptr;
|
||||||
gdni.classdb_register_extension_class_signal = nullptr;
|
gdni.classdb_register_extension_class_signal = nullptr;
|
||||||
gdni.classdb_unregister_extension_class = nullptr;
|
gdni.classdb_unregister_extension_class = nullptr;
|
||||||
|
|
||||||
|
gdni.get_library_path = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -545,6 +545,9 @@ typedef struct {
|
||||||
void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);
|
void (*classdb_register_extension_class_property_subgroup)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);
|
||||||
void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
|
void (*classdb_register_extension_class_signal)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
|
||||||
void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */
|
void (*classdb_unregister_extension_class)(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */
|
||||||
|
|
||||||
|
void (*get_library_path)(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path);
|
||||||
|
|
||||||
} GDNativeInterface;
|
} GDNativeInterface;
|
||||||
|
|
||||||
/* INITIALIZATION */
|
/* INITIALIZATION */
|
||||||
|
|
|
@ -261,8 +261,14 @@ void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLi
|
||||||
self->extension_classes.erase(class_name);
|
self->extension_classes.erase(class_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeExtension::_get_library_path(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path) {
|
||||||
|
NativeExtension *self = static_cast<NativeExtension *>(p_library);
|
||||||
|
|
||||||
|
*(String *)r_path = self->library_path;
|
||||||
|
}
|
||||||
|
|
||||||
Error NativeExtension::open_library(const String &p_path, const String &p_entry_symbol) {
|
Error NativeExtension::open_library(const String &p_path, const String &p_entry_symbol) {
|
||||||
Error err = OS::get_singleton()->open_dynamic_library(p_path, library, true);
|
Error err = OS::get_singleton()->open_dynamic_library(p_path, library, true, &library_path);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -354,6 +360,7 @@ void NativeExtension::initialize_native_extensions() {
|
||||||
gdnative_interface.classdb_register_extension_class_property_subgroup = _register_extension_class_property_subgroup;
|
gdnative_interface.classdb_register_extension_class_property_subgroup = _register_extension_class_property_subgroup;
|
||||||
gdnative_interface.classdb_register_extension_class_signal = _register_extension_class_signal;
|
gdnative_interface.classdb_register_extension_class_signal = _register_extension_class_signal;
|
||||||
gdnative_interface.classdb_unregister_extension_class = _unregister_extension_class;
|
gdnative_interface.classdb_unregister_extension_class = _unregister_extension_class;
|
||||||
|
gdnative_interface.get_library_path = _get_library_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
RES NativeExtensionResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
|
RES NativeExtensionResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
|
||||||
|
|
|
@ -39,6 +39,7 @@ class NativeExtension : public Resource {
|
||||||
GDCLASS(NativeExtension, Resource)
|
GDCLASS(NativeExtension, Resource)
|
||||||
|
|
||||||
void *library = nullptr; // pointer if valid,
|
void *library = nullptr; // pointer if valid,
|
||||||
|
String library_path;
|
||||||
|
|
||||||
struct Extension {
|
struct Extension {
|
||||||
ObjectNativeExtension native_extension;
|
ObjectNativeExtension native_extension;
|
||||||
|
@ -54,6 +55,7 @@ class NativeExtension : public Resource {
|
||||||
static void _register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);
|
static void _register_extension_class_property_subgroup(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_subgroup_name, const char *p_prefix);
|
||||||
static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
|
static void _register_extension_class_signal(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name, const char *p_signal_name, const GDNativePropertyInfo *p_argument_info, GDNativeInt p_argument_count);
|
||||||
static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name);
|
static void _unregister_extension_class(const GDNativeExtensionClassLibraryPtr p_library, const char *p_class_name);
|
||||||
|
static void _get_library_path(const GDNativeExtensionClassLibraryPtr p_library, GDNativeStringPtr r_path);
|
||||||
|
|
||||||
GDNativeInitialization initialization;
|
GDNativeInitialization initialization;
|
||||||
int32_t level_initialized = -1;
|
int32_t level_initialized = -1;
|
||||||
|
|
|
@ -137,7 +137,7 @@ public:
|
||||||
|
|
||||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
|
||||||
|
|
||||||
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) { return ERR_UNAVAILABLE; }
|
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) { return ERR_UNAVAILABLE; }
|
||||||
virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; }
|
virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; }
|
||||||
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) { return ERR_UNAVAILABLE; }
|
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) { return ERR_UNAVAILABLE; }
|
||||||
|
|
||||||
|
|
|
@ -429,7 +429,7 @@ String OS_Unix::get_locale() const {
|
||||||
return locale;
|
return locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
|
Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
|
||||||
String path = p_path;
|
String path = p_path;
|
||||||
|
|
||||||
if (FileAccess::exists(path) && path.is_relative_path()) {
|
if (FileAccess::exists(path) && path.is_relative_path()) {
|
||||||
|
@ -450,6 +450,11 @@ Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle
|
||||||
|
|
||||||
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
||||||
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ". Error: " + dlerror());
|
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ". Error: " + dlerror());
|
||||||
|
|
||||||
|
if (r_resolved_path != nullptr) {
|
||||||
|
*r_resolved_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ public:
|
||||||
|
|
||||||
virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override; // Should return cryptographycally-safe random bytes.
|
virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override; // Should return cryptographycally-safe random bytes.
|
||||||
|
|
||||||
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
|
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
|
||||||
virtual Error close_dynamic_library(void *p_library_handle) override;
|
virtual Error close_dynamic_library(void *p_library_handle) override;
|
||||||
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
|
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
|
||||||
|
|
||||||
|
|
|
@ -162,9 +162,14 @@ Vector<String> OS_Android::get_granted_permissions() const {
|
||||||
return godot_java->get_granted_permissions();
|
return godot_java->get_granted_permissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_Android::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
|
Error OS_Android::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
|
||||||
p_library_handle = dlopen(p_path.utf8().get_data(), RTLD_NOW);
|
p_library_handle = dlopen(p_path.utf8().get_data(), RTLD_NOW);
|
||||||
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + dlerror() + ".");
|
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + dlerror() + ".");
|
||||||
|
|
||||||
|
if (r_resolved_path != nullptr) {
|
||||||
|
*r_resolved_path = p_path;
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ public:
|
||||||
|
|
||||||
virtual void alert(const String &p_alert, const String &p_title) override;
|
virtual void alert(const String &p_alert, const String &p_title) override;
|
||||||
|
|
||||||
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
|
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
|
||||||
|
|
||||||
virtual String get_name() const override;
|
virtual String get_name() const override;
|
||||||
virtual MainLoop *get_main_loop() const override;
|
virtual MainLoop *get_main_loop() const override;
|
||||||
|
|
|
@ -92,7 +92,7 @@ public:
|
||||||
|
|
||||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
||||||
|
|
||||||
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
|
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
|
||||||
virtual Error close_dynamic_library(void *p_library_handle) override;
|
virtual Error close_dynamic_library(void *p_library_handle) override;
|
||||||
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
|
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
|
||||||
|
|
||||||
|
|
|
@ -204,12 +204,17 @@ void OSIPhone::finalize() {
|
||||||
|
|
||||||
// MARK: Dynamic Libraries
|
// MARK: Dynamic Libraries
|
||||||
|
|
||||||
Error OSIPhone::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
|
Error OSIPhone::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
|
||||||
if (p_path.length() == 0) {
|
if (p_path.length() == 0) {
|
||||||
p_library_handle = RTLD_SELF;
|
p_library_handle = RTLD_SELF;
|
||||||
|
|
||||||
|
if (r_resolved_path != nullptr) {
|
||||||
|
*r_resolved_path = p_path;
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
return OS_Unix::open_dynamic_library(p_path, p_library_handle, p_also_set_library_path);
|
return OS_Unix::open_dynamic_library(p_path, p_library_handle, p_also_set_library_path, r_resolved_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OSIPhone::close_dynamic_library(void *p_library_handle) {
|
Error OSIPhone::close_dynamic_library(void *p_library_handle) {
|
||||||
|
|
|
@ -221,10 +221,15 @@ bool OS_JavaScript::is_userfs_persistent() const {
|
||||||
return idb_available;
|
return idb_available;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_JavaScript::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
|
Error OS_JavaScript::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
|
||||||
String path = p_path.get_file();
|
String path = p_path.get_file();
|
||||||
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
||||||
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ". Error: " + dlerror());
|
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ". Error: " + dlerror());
|
||||||
|
|
||||||
|
if (r_resolved_path != nullptr) {
|
||||||
|
*r_resolved_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ public:
|
||||||
|
|
||||||
void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
||||||
|
|
||||||
Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) override;
|
Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
|
||||||
|
|
||||||
void resume_audio();
|
void resume_audio();
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ public:
|
||||||
|
|
||||||
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
|
||||||
|
|
||||||
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
|
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
|
||||||
|
|
||||||
virtual MainLoop *get_main_loop() const override;
|
virtual MainLoop *get_main_loop() const override;
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ void OS_OSX::alert(const String &p_alert, const String &p_title) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_OSX::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
|
Error OS_OSX::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
|
||||||
String path = get_framework_executable(p_path);
|
String path = get_framework_executable(p_path);
|
||||||
|
|
||||||
if (!FileAccess::exists(path)) {
|
if (!FileAccess::exists(path)) {
|
||||||
|
@ -165,6 +165,11 @@ Error OS_OSX::open_dynamic_library(const String p_path, void *&p_library_handle,
|
||||||
|
|
||||||
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
|
||||||
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + dlerror() + ".");
|
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + dlerror() + ".");
|
||||||
|
|
||||||
|
if (r_resolved_path != nullptr) {
|
||||||
|
*r_resolved_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -733,10 +733,15 @@ static String format_error_message(DWORD id) {
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_UWP::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
|
Error OS_UWP::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
|
||||||
String full_path = "game/" + p_path;
|
String full_path = "game/" + p_path;
|
||||||
p_library_handle = (void *)LoadPackagedLibrary((LPCWSTR)(full_path.utf16().get_data()), 0);
|
p_library_handle = (void *)LoadPackagedLibrary((LPCWSTR)(full_path.utf16().get_data()), 0);
|
||||||
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + full_path + ", error: " + format_error_message(GetLastError()) + ".");
|
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + full_path + ", error: " + format_error_message(GetLastError()) + ".");
|
||||||
|
|
||||||
|
if (r_resolved_path != nullptr) {
|
||||||
|
*r_resolved_path = full_path;
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -233,7 +233,7 @@ public:
|
||||||
virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
|
virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
|
||||||
virtual void hide_virtual_keyboard();
|
virtual void hide_virtual_keyboard();
|
||||||
|
|
||||||
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false);
|
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr);
|
||||||
virtual Error close_dynamic_library(void *p_library_handle);
|
virtual Error close_dynamic_library(void *p_library_handle);
|
||||||
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false);
|
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false);
|
||||||
|
|
||||||
|
|
|
@ -202,7 +202,7 @@ Error OS_Windows::get_entropy(uint8_t *r_buffer, int p_bytes) {
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
|
Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
|
||||||
String path = p_path.replace("/", "\\");
|
String path = p_path.replace("/", "\\");
|
||||||
|
|
||||||
if (!FileAccess::exists(path)) {
|
if (!FileAccess::exists(path)) {
|
||||||
|
@ -230,6 +230,10 @@ Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_han
|
||||||
remove_dll_directory(cookie);
|
remove_dll_directory(cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r_resolved_path != nullptr) {
|
||||||
|
*r_resolved_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ public:
|
||||||
|
|
||||||
virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override;
|
virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override;
|
||||||
|
|
||||||
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
|
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
|
||||||
virtual Error close_dynamic_library(void *p_library_handle) override;
|
virtual Error close_dynamic_library(void *p_library_handle) override;
|
||||||
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
|
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue