diff options
Diffstat (limited to 'modules/mono/mono_gd')
-rw-r--r-- | modules/mono/mono_gd/gd_mono_android.cpp | 116 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_android.h | 18 |
2 files changed, 134 insertions, 0 deletions
diff --git a/modules/mono/mono_gd/gd_mono_android.cpp b/modules/mono/mono_gd/gd_mono_android.cpp new file mode 100644 index 0000000000..42983e1821 --- /dev/null +++ b/modules/mono/mono_gd/gd_mono_android.cpp @@ -0,0 +1,116 @@ +#include "gd_mono_android.h" + +#if defined(ANDROID_ENABLED) + +#include <dlfcn.h> // dlopen, dlsym +#include <mono/utils/mono-dl-fallback.h> + +#include "core/os/os.h" +#include "core/ustring.h" +#include "platform/android/thread_jandroid.h" + +#include "../utils/path_utils.h" +#include "../utils/string_utils.h" + +namespace GDMonoAndroid { + +String app_native_lib_dir_cache; + +String determine_app_native_lib_dir() { + JNIEnv *env = ThreadAndroid::get_env(); + + jclass activityThreadClass = env->FindClass("android/app/ActivityThread"); + jmethodID currentActivityThread = env->GetStaticMethodID(activityThreadClass, "currentActivityThread", "()Landroid/app/ActivityThread;"); + jobject activityThread = env->CallStaticObjectMethod(activityThreadClass, currentActivityThread); + jmethodID getApplication = env->GetMethodID(activityThreadClass, "getApplication", "()Landroid/app/Application;"); + jobject ctx = env->CallObjectMethod(activityThread, getApplication); + + jmethodID getApplicationInfo = env->GetMethodID(env->GetObjectClass(ctx), "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;"); + jobject applicationInfo = env->CallObjectMethod(ctx, getApplicationInfo); + jfieldID nativeLibraryDirField = env->GetFieldID(env->GetObjectClass(applicationInfo), "nativeLibraryDir", "Ljava/lang/String;"); + jstring nativeLibraryDir = (jstring)env->GetObjectField(applicationInfo, nativeLibraryDirField); + + String result; + + const char *const nativeLibraryDir_utf8 = env->GetStringUTFChars(nativeLibraryDir, NULL); + if (nativeLibraryDir_utf8) { + result.parse_utf8(nativeLibraryDir_utf8); + env->ReleaseStringUTFChars(nativeLibraryDir, nativeLibraryDir_utf8); + } + + return result; +} + +String get_app_native_lib_dir() { + if (app_native_lib_dir_cache.empty()) + app_native_lib_dir_cache = determine_app_native_lib_dir(); + return app_native_lib_dir_cache; +} + +int gd_mono_convert_dl_flags(int flags) { + // from mono's runtime-bootstrap.c + + int lflags = flags & MONO_DL_LOCAL ? 0 : RTLD_GLOBAL; + + if (flags & MONO_DL_LAZY) + lflags |= RTLD_LAZY; + else + lflags |= RTLD_NOW; + + return lflags; +} + +void *gd_mono_android_dlopen(const char *p_name, int p_flags, char **r_err, void *p_user_data) { + String name = String::utf8(p_name); + + if (name.ends_with(".dll.so") || name.ends_with(".exe.so")) { + String app_native_lib_dir = get_app_native_lib_dir(); + + String orig_so_name = name.get_file(); + String so_name = "lib-aot-" + orig_so_name; + String so_path = path::join(app_native_lib_dir, so_name); + + if (!FileAccess::exists(so_path)) { + if (OS::get_singleton()->is_stdout_verbose()) + OS::get_singleton()->print("Cannot find shared library: '%s'\n", so_path.utf8().get_data()); + return NULL; + } + + int lflags = gd_mono_convert_dl_flags(p_flags); + + void *handle = dlopen(so_path.utf8().get_data(), lflags); + + if (!handle) { + if (OS::get_singleton()->is_stdout_verbose()) + OS::get_singleton()->print("Failed to open shared library: '%s'. Error: '%s'\n", so_path.utf8().get_data(), dlerror()); + return NULL; + } + + if (OS::get_singleton()->is_stdout_verbose()) + OS::get_singleton()->print("Successfully loaded AOT shared library: '%s'\n", so_path.utf8().get_data()); + + return handle; + } + + return NULL; +} + +void *gd_mono_android_dlsym(void *p_handle, const char *p_name, char **r_err, void *p_user_data) { + void *sym_addr = dlsym(p_handle, p_name); + + if (sym_addr) + return sym_addr; + + if (r_err) + *r_err = str_format_new("%s\n", dlerror()); + + return NULL; +} + +void register_android_dl_fallback() { + mono_dl_fallback_register(gd_mono_android_dlopen, gd_mono_android_dlsym, NULL, NULL); +} + +} // namespace GDMonoAndroid + +#endif diff --git a/modules/mono/mono_gd/gd_mono_android.h b/modules/mono/mono_gd/gd_mono_android.h new file mode 100644 index 0000000000..52705fbd2d --- /dev/null +++ b/modules/mono/mono_gd/gd_mono_android.h @@ -0,0 +1,18 @@ +#ifndef GD_MONO_ANDROID_H +#define GD_MONO_ANDROID_H + +#if defined(ANDROID_ENABLED) + +#include "core/ustring.h" + +namespace GDMonoAndroid { + +String get_app_native_lib_dir(); + +void register_android_dl_fallback(); + +} // namespace GDMonoAndroid + +#endif // ANDROID_ENABLED + +#endif // GD_MONO_ANDROID_H |