summaryrefslogtreecommitdiff
path: root/modules/mono/mono_gd
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono/mono_gd')
-rw-r--r--modules/mono/mono_gd/gd_mono_android.cpp116
-rw-r--r--modules/mono/mono_gd/gd_mono_android.h18
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