Make GDNative work on Android

The changes include work done to ensure that GDNative apps and Nim
integration specifically can run on Android. The changes have been
tested on our WIP game, which uses godot-nim and depends on several
third-party .so libs, and Platformer demo to ensure nothing got broken.

 - .so libraries are exported to lib/ folder in .apk, instead of assets/,
   because that's where Android expects them to be and it resolves the
   library name into "lib/<ABI>/<name>", where <ABI> is the ABI matching
   the current device. So we establish the convention that Android .so
   files in the project must be located in the folder corresponding to
   the ABI they were compiled for.

 - Godot callbacks (event handlers) are now called from the same thread
   from which Main::iteration is called. It is also what Godot now
   considers to be the main thread, because Main::setup is also called
   from there. This makes threading on Android more consistent with
   other platforms, making the code that depends on Thread::get_main_id
   more portable (GDNative has such code).

 - Sizes of GDNative API types have been fixed to work on 32-bit
   platforms.
This commit is contained in:
Ruslan Mustakov
2017-08-18 21:17:35 +07:00
parent 8b9026c05e
commit 5ccdeccb6e
22 changed files with 447 additions and 321 deletions

View File

@@ -40,7 +40,7 @@
const String init_symbol = "godot_gdnative_init";
const String terminate_symbol = "godot_gdnative_terminate";
String GDNativeLibrary::platform_names[NUM_PLATFORMS] = {
String GDNativeLibrary::platform_names[NUM_PLATFORMS + 1] = {
"X11_32bit",
"X11_64bit",
"Windows_32bit",
@@ -48,11 +48,15 @@ String GDNativeLibrary::platform_names[NUM_PLATFORMS] = {
"OSX",
"Android",
"iOS",
"WebAssembly"
"iOS_32bit",
"iOS_64bit",
"WebAssembly",
""
};
String GDNativeLibrary::platform_lib_ext[NUM_PLATFORMS] = {
String GDNativeLibrary::platform_lib_ext[NUM_PLATFORMS + 1] = {
"so",
"so",
"dll",
@@ -60,21 +64,30 @@ String GDNativeLibrary::platform_lib_ext[NUM_PLATFORMS] = {
"dylib",
"so",
"dylib",
"dylib",
"wasm"
"wasm",
""
};
// TODO(karroffel): make this actually do the right thing.
GDNativeLibrary::Platform GDNativeLibrary::current_platform =
#if defined(X11_ENABLED)
X11_64BIT;
(sizeof(void *) == 8 ? X11_64BIT : X11_32BIT);
#elif defined(WINDOWS_ENABLED)
WINDOWS_64BIT;
(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
X11_64BIT; // need a sensible default..
NUM_PLATFORMS;
#endif
GDNativeLibrary::GDNativeLibrary()
@@ -151,7 +164,10 @@ String GDNativeLibrary::get_library_path(StringName p_platform) const {
}
String GDNativeLibrary::get_active_library_path() const {
return library_paths[GDNativeLibrary::current_platform];
if (GDNativeLibrary::current_platform != NUM_PLATFORMS) {
return library_paths[GDNativeLibrary::current_platform];
}
return "";
}
GDNative::GDNative() {

View File

@@ -48,11 +48,17 @@ class GDNativeLibrary : public Resource {
// NOTE(karroffel): I heard OSX 32 bit is dead, so 64 only
OSX,
// TODO(karroffel): all different android versions and archs
// 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,
// TODO(karroffe): all different iOS versions and archs
IOS,
IOS_32BIT,
IOS_64BIT,
// TODO(karroffel): figure out how to deal with web stuff at all...
WASM,
@@ -64,10 +70,9 @@ class GDNativeLibrary : public Resource {
};
static String platform_names[NUM_PLATFORMS];
static String platform_lib_ext[NUM_PLATFORMS];
static String platform_names[NUM_PLATFORMS + 1];
static String platform_lib_ext[NUM_PLATFORMS + 1];
// TODO(karroffel): make this actually do something lol.
static Platform current_platform;
String library_paths[NUM_PLATFORMS];

View File

@@ -37,7 +37,7 @@ extern "C" {
#include <stdint.h>
#define GODOT_ARRAY_SIZE 8
#define GODOT_ARRAY_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_ARRAY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_ARRAY_TYPE_DEFINED

View File

@@ -36,7 +36,7 @@ extern "C" {
#include <stdint.h>
#define GODOT_DICTIONARY_SIZE 8
#define GODOT_DICTIONARY_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_DICTIONARY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_DICTIONARY_TYPE_DEFINED

View File

@@ -56,7 +56,7 @@ extern "C" {
#define GDAPI GDCALLINGCONV
#endif
#else
#define GDCALLINGCONV __attribute__((sysv_abi))
#define GDCALLINGCONV __attribute__((sysv_abi, visibility("default")))
#define GDAPI GDCALLINGCONV
#endif

View File

@@ -36,7 +36,7 @@ extern "C" {
#include <stdint.h>
#define GODOT_NODE_PATH_SIZE 8
#define GODOT_NODE_PATH_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_NODE_PATH_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_NODE_PATH_TYPE_DEFINED

View File

@@ -38,7 +38,7 @@ extern "C" {
/////// PoolByteArray
#define GODOT_POOL_BYTE_ARRAY_SIZE 8
#define GODOT_POOL_BYTE_ARRAY_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_POOL_BYTE_ARRAY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_POOL_BYTE_ARRAY_TYPE_DEFINED
@@ -49,7 +49,7 @@ typedef struct {
/////// PoolIntArray
#define GODOT_POOL_INT_ARRAY_SIZE 8
#define GODOT_POOL_INT_ARRAY_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_POOL_INT_ARRAY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_POOL_INT_ARRAY_TYPE_DEFINED
@@ -60,7 +60,7 @@ typedef struct {
/////// PoolRealArray
#define GODOT_POOL_REAL_ARRAY_SIZE 8
#define GODOT_POOL_REAL_ARRAY_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_POOL_REAL_ARRAY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_POOL_REAL_ARRAY_TYPE_DEFINED
@@ -71,7 +71,7 @@ typedef struct {
/////// PoolStringArray
#define GODOT_POOL_STRING_ARRAY_SIZE 8
#define GODOT_POOL_STRING_ARRAY_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_POOL_STRING_ARRAY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_POOL_STRING_ARRAY_TYPE_DEFINED
@@ -82,7 +82,7 @@ typedef struct {
/////// PoolVector2Array
#define GODOT_POOL_VECTOR2_ARRAY_SIZE 8
#define GODOT_POOL_VECTOR2_ARRAY_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_POOL_VECTOR2_ARRAY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_POOL_VECTOR2_ARRAY_TYPE_DEFINED
@@ -93,7 +93,7 @@ typedef struct {
/////// PoolVector3Array
#define GODOT_POOL_VECTOR3_ARRAY_SIZE 8
#define GODOT_POOL_VECTOR3_ARRAY_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_POOL_VECTOR3_ARRAY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_POOL_VECTOR3_ARRAY_TYPE_DEFINED
@@ -104,7 +104,7 @@ typedef struct {
/////// PoolColorArray
#define GODOT_POOL_COLOR_ARRAY_SIZE 8
#define GODOT_POOL_COLOR_ARRAY_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_POOL_COLOR_ARRAY_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_POOL_COLOR_ARRAY_TYPE_DEFINED

View File

@@ -36,7 +36,7 @@ extern "C" {
#include <stdint.h>
#define GODOT_RID_SIZE 8
#define GODOT_RID_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_RID_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_RID_TYPE_DEFINED

View File

@@ -37,7 +37,7 @@ extern "C" {
#include <stdint.h>
#include <wchar.h>
#define GODOT_STRING_SIZE 8
#define GODOT_STRING_SIZE sizeof(void *)
#ifndef GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED

View File

@@ -36,7 +36,7 @@ extern "C" {
#include <stdint.h>
#define GODOT_VARIANT_SIZE 24
#define GODOT_VARIANT_SIZE (16 + sizeof(void *))
#ifndef GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED
#define GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED

View File

@@ -58,7 +58,7 @@ extern "C" {
#define GDAPI GDCALLINGCONV
#endif
#else
#define GDCALLINGCONV __attribute__((sysv_abi))
#define GDCALLINGCONV __attribute__((sysv_abi, visibility("default")))
#define GDAPI GDCALLINGCONV
#endif

View File

@@ -994,6 +994,8 @@ void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) {
#endif
// See if this library was "registered" already.
const String &lib_path = lib->get_active_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);
if (!E) {