C++RAW #include "UnityPrefix.h" #include "Runtime/Scripting/ScriptingUtility.h" #include "Runtime/Mono/MonoBehaviour.h" #include "Runtime/Mono/MonoScopedThreadAttach.h" #if UNITY_ANDROID #if UNITY_DEVELOPER_BUILD static volatile bool DEBUGJNI = false; #else #define DEBUGJNI 0 #endif #define DEBUGJNI_VERBOSE 0 #include "PlatformDependent/AndroidPlayer/EntryPoint.h" static MonoDomain* s_MonoDomain = 0; jobject UnityJavaProxy_invoke(JNIEnv*, jobject thiz, jint delegate, jstring method, jobjectArray args) { ScopedThreadAttach mono(s_MonoDomain); MonoObject* proxy = mono_gchandle_get_target(delegate); void* params[] = {proxy, &method, &args}; MonoObject* mresult = CallStaticMonoMethod("_AndroidJNIHelper", "InvokeJavaProxyMethod", params); if (!mresult) return 0; return ExtractMonoObjectData(mresult); } void UnityJavaProxy_finalize(JNIEnv*, jobject thiz, jint jdelegate) { ScopedThreadAttach mono(s_MonoDomain); mono_gchandle_free(jdelegate); } #if DEBUGJNI #define SCOPED_JNI(x) DalvikAttachThreadScoped jni_env(x) #else #define SCOPED_JNI(x) DalvikAttachThreadScoped jni_env("AndroidJNI") #endif #define JNI_GET_ID( GetIDFunc ) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return 0; \ string methodName = name; \ string signature = sig; \ if (DEBUGJNI) \ printf_console("> %s(%08x, %s, %s)", __FUNCTION__, clazz, methodName.c_str(), signature.c_str()); \ if (clazz == 0) \ return 0; \ return jni_env->GetIDFunc((jclass)clazz, methodName.c_str(), signature.c_str()); \ } while(0) #define ConvertToJNIArgs() \ int numargs = mono_array_length(args); \ jvalue* jni_args = (jvalue*)alloca(sizeof(jvalue) * numargs); \ for (int i = 0; i < numargs; ++i) \ { \ jni_args[i] = GetMonoArrayElement(args, i); \ if (DEBUGJNI) \ printf_console(">\t\t\t, %08x", jni_args[i].i); \ } \ if (DEBUGJNI && numargs) \ printf_console(">\t\t\t)"); #define JNI_CALL_METHOD( MethodFunc, ClassOrObj ) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return 0; \ if (DEBUGJNI) \ printf_console("> %s(%08x, %08x%s", __FUNCTION__, ClassOrObj, \ (jmethodID)methodID, mono_array_length(args) ? " " : ")"); \ if (ClassOrObj == 0 || (jmethodID)methodID == 0) \ return 0; \ ConvertToJNIArgs(); \ return jni_env->MethodFunc(ClassOrObj, (jmethodID)methodID, jni_args); \ } while(0) #define JNI_CALL_VOID_METHOD( MethodFunc, ClassOrObj ) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return; \ if (DEBUGJNI) \ printf_console("> %s(%08x, %08x%s", __FUNCTION__, ClassOrObj, \ (jmethodID)methodID, mono_array_length(args) ? " " : ")"); \ if (ClassOrObj == 0 || (jmethodID)methodID == 0) \ return; \ ConvertToJNIArgs(); \ jni_env->MethodFunc(ClassOrObj, (jmethodID)methodID, jni_args); \ } while(0) #define JNI_GET_FIELD( FieldFunc, ClassOrObj ) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return 0; \ if (DEBUGJNI) \ printf_console("> %s(%08x)", __FUNCTION__, ClassOrObj); \ if (ClassOrObj == 0 || (jmethodID)fieldID == 0) \ return 0; \ return jni_env->FieldFunc(ClassOrObj, (jfieldID)fieldID); \ } while(0) #define JNI_SET_FIELD( FieldFunc, ClassOrObj, Value ) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return; \ if (DEBUGJNI) \ printf_console("> %s(%08x)", __FUNCTION__, ClassOrObj); \ if (ClassOrObj == 0 || (jmethodID)fieldID == 0) \ return; \ jni_env->FieldFunc(ClassOrObj, (jfieldID)fieldID, Value); \ } while(0) #define JNI_PASS_VOID_VOID( Func ) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return; \ if (DEBUGJNI) \ printf_console("> %s()", __FUNCTION__); \ jni_env->Func(); \ } while(0) #define JNI_PASS_RETV_VOID( Func ) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return 0; \ if (DEBUGJNI) \ printf_console("> %s()", __FUNCTION__); \ return jni_env->Func(); \ } while(0) #define JNI_PASS_VOID_ARGS( Func, ...) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return; \ if (DEBUGJNI) \ printf_console("> %s()", __FUNCTION__); \ jni_env->Func(__VA_ARGS__); \ } while(0) #define JNI_PASS_RETV_ARGS( Func, ...) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return 0; \ if (DEBUGJNI) \ printf_console("> %s()", __FUNCTION__); \ return jni_env->Func(__VA_ARGS__); \ } while(0) #define JNI_GET_JSTR_FIELD( FieldFunc, ClassOrObj ) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return SCRIPTING_NULL; \ if (DEBUGJNI) \ printf_console("> %s(%08x)", __FUNCTION__, ClassOrObj); \ if (ClassOrObj == 0 || (jmethodID)fieldID == 0) \ return SCRIPTING_NULL; \ jstring str = (jstring)jni_env->FieldFunc(ClassOrObj, (jfieldID)fieldID); \ if (str == 0 || jni_env->ExceptionCheck()) return SCRIPTING_NULL; \ const char* cstring = jni_env->GetStringUTFChars(str, 0); \ if (cstring == 0 || jni_env->ExceptionCheck()) \ { \ jni_env->ReleaseStringUTFChars(str, cstring); \ jni_env->DeleteLocalRef(str); \ return SCRIPTING_NULL; \ } \ MonoString* mstring = scripting_string_new(cstring); \ jni_env->ReleaseStringUTFChars(str, cstring); \ jni_env->DeleteLocalRef(str); \ return mstring; \ } while(0) #define JNI_CALL_JSTR_METHOD( MethodFunc, ClassOrObj ) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return SCRIPTING_NULL; \ if (DEBUGJNI) \ printf_console("> %s(%08x, %08x%s", __FUNCTION__, ClassOrObj, \ (jmethodID)methodID, mono_array_length(args) ? " " : ")"); \ if (ClassOrObj == 0 || (jmethodID)methodID == 0) \ return SCRIPTING_NULL; \ ConvertToJNIArgs(); \ jstring str = (jstring)jni_env->MethodFunc(ClassOrObj, (jmethodID)methodID, jni_args); \ if (str == 0 || jni_env->ExceptionCheck()) return SCRIPTING_NULL; \ const char* cstring = jni_env->GetStringUTFChars(str, 0); \ if (cstring == 0 || jni_env->ExceptionCheck()) \ { \ jni_env->ReleaseStringUTFChars(str, cstring); \ jni_env->DeleteLocalRef(str); \ return SCRIPTING_NULL; \ } \ MonoString* mstring = scripting_string_new(cstring); \ jni_env->ReleaseStringUTFChars(str, cstring); \ jni_env->DeleteLocalRef(str); \ return mstring; \ } while(0) #define JNI_NEW_ARRAY( NewArrayType, Type, ArrayType ) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return SCRIPTING_NULL; \ int size = mono_array_length(array); \ ArrayType jni_array = jni_env->New ## NewArrayType ## Array(size); \ if (jni_array == 0 || jni_env->ExceptionCheck()) return SCRIPTING_NULL; \ for (int i = 0; i < size; ++i) \ { \ Type val = GetMonoArrayElement(array, i); \ jni_env->Set ## NewArrayType ## ArrayRegion(jni_array, i, 1, &val); \ if (jni_env->ExceptionCheck()) return SCRIPTING_NULL; \ } \ return jni_array; \ } while(0) #define JNI_GET_ARRAY( GetArrayType, Type, ArrayType, ArrayClass ) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return SCRIPTING_NULL; \ jsize length = jni_env->GetArrayLength((jarray)array); \ if (jni_env->ExceptionCheck()) return SCRIPTING_NULL; \ MonoArray* csarray = mono_array_new(mono_domain_get(), ArrayClass, length); \ Type* mem = jni_env->Get ## GetArrayType ## ArrayElements((ArrayType)array, 0); \ if (jni_env->ExceptionCheck()) return SCRIPTING_NULL; \ for (int i = 0; i < length; ++i) \ Scripting::SetScriptingArrayElement(csarray, i, mem[i]); \ jni_env->Release ## GetArrayType ## ArrayElements((ArrayType)array, mem, JNI_ABORT); \ return csarray; \ } while(0) #define JNI_GET_ARRAY_ELEMENT( GetArrayType, Type, ArrayType ) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return 0; \ Type val; \ jni_env->Get ## GetArrayType ## ArrayRegion((ArrayType)array, index, 1, &val); \ return val; \ } while(0) #define JNI_SET_ARRAY_ELEMENT( SetArrayType, Type, ArrayType ) \ do { \ SCOPED_JNI(__FUNCTION__); \ if (!jni_env) return; \ jni_env->Get ## SetArrayType ## ArrayRegion((ArrayType)array, index, 1, &val); \ } while(0) struct jStringWrapper { std::string cString; jstring javaString; jStringWrapper(ICallString& cs) : javaString(0) { cString = cs; if (DEBUGJNI_VERBOSE) printf_console("> [%s](\"%s\")", __FUNCTION__, cString.c_str()); } ~jStringWrapper() { if (DEBUGJNI_VERBOSE) printf_console("> [%s](\"%s\")", __FUNCTION__, cString.c_str()); if (!javaString) return; SCOPED_JNI(__FUNCTION__); if (!jni_env) return; jni_env->DeleteLocalRef(javaString); } operator jstring() { if (DEBUGJNI_VERBOSE) printf_console("> [%s](\"%s\")", __FUNCTION__, cString.c_str()); SCOPED_JNI(__FUNCTION__); if (!jni_env) return 0; javaString = jni_env->NewStringUTF(cString.c_str()); return javaString; } operator const char*() { if (DEBUGJNI_VERBOSE) printf_console("> [%s](\"%s\")", __FUNCTION__, cString.c_str()); return cString.c_str(); } }; #else // UNITY_ANDROID typedef void* jobject; typedef void* jclass; #define JNI_GET_ID( GetIDFunc ) do { return 0; } while(0) #define JNI_CALL_METHOD( MethodFunc, ClassOrObj ) do { (void)ClassOrObj; return 0; } while(0) #define JNI_CALL_VOID_METHOD( MethodFunc, ClassOrObj ) do { (void)ClassOrObj; } while(0) #define JNI_GET_FIELD( FieldFunc, ClassOrObj ) do { (void)ClassOrObj; return 0; } while(0) #define JNI_GET_JSTR_FIELD( FieldFunc, ClassOrObj ) do { (void)ClassOrObj; return SCRIPTING_NULL; } while(0) #define JNI_SET_FIELD( FieldFunc, ClassOrObj, Value ) do { (void)ClassOrObj; (void)Value; } while(0) #define JNI_PASS_VOID_VOID( Func ) do { ; } while(0) #define JNI_PASS_RETV_VOID( Func) do { return 0; } while(0) #define JNI_PASS_VOID_ARGS( Func, ...) do { ; } while(0) #define JNI_PASS_RETV_ARGS( Func, ...) do { return 0; } while(0) #define JNI_CALL_JSTR_METHOD( MethodFunc, ClassOrObj ) do { (void)ClassOrObj; return SCRIPTING_NULL; } while(0) #define JNI_NEW_ARRAY( NewArrayFunc, Type, ArrayType ) do { return SCRIPTING_NULL; } while(0) #define JNI_GET_ARRAY( GetArrayType, Type, ArrayType, ArrayClass ) do { return SCRIPTING_NULL; } while(0) #define JNI_GET_ARRAY_ELEMENT( GetArrayType, Type, ArrayType ) do { return 0; } while(0) #define JNI_SET_ARRAY_ELEMENT( SetArrayType, Type, ArrayType ) do { ; } while(0) #endif CSRAW #if UNITY_EDITOR || UNITY_ANDROID using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace UnityEngine { [StructLayout(LayoutKind.Explicit)] public struct jvalue { [FieldOffset(0)] public bool z; [FieldOffset(0)] public byte b; [FieldOffset(0)] public char c; [FieldOffset(0)] public short s; [FieldOffset(0)] public int i; [FieldOffset(0)] public long j; [FieldOffset(0)] public float f; [FieldOffset(0)] public double d; [FieldOffset(0)] public System.IntPtr l; } // Helper interface for JNI interaction; signature creation and method lookups CONDITIONAL !UNITY_WINRT CLASS AndroidJNIHelper CSRAW private AndroidJNIHelper() {} // Set /debug/ to true to log calls through the AndroidJNIHelper CUSTOM_PROP static bool debug { #if UNITY_ANDROID && UNITY_DEVELOPER_BUILD return DEBUGJNI; #else return false; #endif } { #if UNITY_ANDROID && UNITY_DEVELOPER_BUILD DEBUGJNI = value; SCOPED_JNI(__FUNCTION__); if (!jni_env) return; jclass cls_up = jni_env->FindClass("com/unity3d/player/ReflectionHelper"); if (!cls_up || jni_env->ExceptionCheck()) return; jfieldID fid_get = jni_env->GetStaticFieldID(cls_up, "LOG", "Z"); if (!fid_get || jni_env->ExceptionCheck()) { jni_env->DeleteLocalRef(cls_up); return; } jni_env->SetStaticBooleanField(cls_up, fid_get, value); jni_env->DeleteLocalRef(cls_up); #endif } // Scans a particular Java class for a constructor method matching a signature. CSRAW public static IntPtr GetConstructorID(IntPtr javaClass, string signature = "") { return _AndroidJNIHelper.GetConstructorID(javaClass, signature); } // Scans a particular Java class for a method matching a name and a signature. CSRAW public static IntPtr GetMethodID(IntPtr javaClass, string methodName, string signature = "", bool isStatic = false) { return _AndroidJNIHelper.GetMethodID(javaClass, methodName, signature, isStatic); } CSRAW public static IntPtr GetFieldID(IntPtr javaClass, string fieldName, string signature = "", bool isStatic = false) { return _AndroidJNIHelper.GetFieldID(javaClass, fieldName, signature, isStatic); } // Creates a UnityJavaRunnable object (implements java.lang.Runnable). CSRAW public static IntPtr CreateJavaRunnable(AndroidJavaRunnable jrunnable) { return _AndroidJNIHelper.CreateJavaRunnable(jrunnable); } // Creates a UnityJavaProxy object (implements jinterface). THREAD_SAFE CUSTOM static IntPtr CreateJavaProxy(AndroidJavaProxy proxy) { #if UNITY_ANDROID s_MonoDomain = mono_domain_get(); int gcHandle = mono_gchandle_new(proxy, 0); void* params[] = { &gcHandle, proxy }; MonoException* exception; MonoObject* result = CallStaticMonoMethod("_AndroidJNIHelper", "CreateJavaProxy", params, &exception); if (exception) { mono_gchandle_free(gcHandle); mono_raise_exception(exception); return 0; } return ExtractMonoObjectData(result); #else return 0; #endif } // Creates a Java array from a managed array CSRAW public static IntPtr ConvertToJNIArray(System.Array array) { return _AndroidJNIHelper.ConvertToJNIArray(array); } // Creates the parameter array to be used as argument list when invoking Java code through CallMethod() in AndroidJNI. CSRAW public static jvalue[] CreateJNIArgArray(object[] args) { return _AndroidJNIHelper.CreateJNIArgArray(args); } // Deletes any local jni references previously allocated by CreateJNIArgArray() // // @param jniArgs the array returned by CreateJNIArgArray() // @param args the array of arguments used as a parameter to CreateJNIArgArray() // CSRAW public static void DeleteJNIArgArray(object[] args, jvalue[] jniArgs) { _AndroidJNIHelper.DeleteJNIArgArray(args, jniArgs); } // Get a JNI method ID for a constructor based on calling arguments. // Scans a particular Java class for a constructor method matching a signature based on passed arguments. // The signature comparison is done to allow for sub-/base-classes of the class types. // // @param javaClass Raw JNI Java class object (obtained by calling AndroidJNI.FindClass). // @param args Array with parameters to be passed to the constructor when invoked. // CSRAW public static System.IntPtr GetConstructorID(System.IntPtr jclass, object[] args) { return _AndroidJNIHelper.GetConstructorID(jclass, args); } // Get a JNI method ID based on calling arguments. CSRAW public static System.IntPtr GetMethodID(System.IntPtr jclass, string methodName, object[] args, bool isStatic) { return _AndroidJNIHelper.GetMethodID(jclass, methodName, args, isStatic); } // Creates the JNI signature string for particular object type CSRAW public static string GetSignature(object obj) { return _AndroidJNIHelper.GetSignature(obj); } // Creates the JNI signature string for an object parameter list. CSRAW public static string GetSignature(object[] args) { return _AndroidJNIHelper.GetSignature(args); } //=================================================================== // Creates a managed array from a Java array CSRAW public static ArrayType ConvertFromJNIArray(IntPtr array) { return _AndroidJNIHelper.ConvertFromJNIArray(array); } // Get a JNI method ID based on calling arguments. CSRAW public static System.IntPtr GetMethodID(System.IntPtr jclass, string methodName, object[] args, bool isStatic) { return _AndroidJNIHelper.GetMethodID(jclass, methodName, args, isStatic); } // Get a JNI field ID based on type detection. Generic parameter represents the field type. CSRAW public static System.IntPtr GetFieldID(System.IntPtr jclass, string fieldName, bool isStatic) { return _AndroidJNIHelper.GetFieldID(jclass, fieldName, isStatic); } // Creates the JNI signature string for an object parameter list. CSRAW public static string GetSignature(object[] args) { return _AndroidJNIHelper.GetSignature(args); } END // 'Raw' JNI interface to Android Dalvik (Java) VM from Mono (CS/JS) CONDITIONAL !UNITY_WINRT CLASS AndroidJNI CSRAW private AndroidJNI() {} // Attaches the current thread to a Java (Dalvik) VM. THREAD_SAFE CUSTOM static int AttachCurrentThread() { #if UNITY_ANDROID JavaVM* vm = GetJavaVm(); Assert(vm); JNIEnv* env; return vm->AttachCurrentThread(&env, 0); #else return 0; #endif } // Detaches the current thread from a Java (Dalvik) VM. THREAD_SAFE CUSTOM static int DetachCurrentThread() { #if UNITY_ANDROID JavaVM* vm = GetJavaVm(); Assert(vm); return vm->DetachCurrentThread(); #else return 0; #endif } // Returns the version of the native method interface. THREAD_SAFE CUSTOM static int GetVersion() { JNI_PASS_RETV_VOID( GetVersion ); } // This function loads a locally-defined class. THREAD_SAFE CUSTOM static IntPtr FindClass(string name) { JNI_PASS_RETV_ARGS( FindClass, jStringWrapper(name) ); } // Converts a java.lang.reflect.Method or java.lang.reflect.Constructor object to a method ID. THREAD_SAFE CUSTOM static IntPtr FromReflectedMethod(IntPtr refMethod) { JNI_PASS_RETV_ARGS( FromReflectedMethod, (jobject)refMethod ); } // Converts a java.lang.reflect.Field to a field ID. THREAD_SAFE CUSTOM static IntPtr FromReflectedField(IntPtr refField) { JNI_PASS_RETV_ARGS( FromReflectedField, (jobject)refField ); } // Converts a method ID derived from clazz to a java.lang.reflect.Method or java.lang.reflect.Constructor object. THREAD_SAFE CUSTOM static IntPtr ToReflectedMethod(IntPtr clazz, IntPtr methodID, bool isStatic) { JNI_PASS_RETV_ARGS( ToReflectedMethod, (jclass)clazz, (jmethodID)methodID, isStatic ); } // Converts a field ID derived from cls to a java.lang.reflect.Field object. THREAD_SAFE CUSTOM static IntPtr ToReflectedField(IntPtr clazz, IntPtr fieldID, bool isStatic) { JNI_PASS_RETV_ARGS( ToReflectedField, (jclass)clazz, (jfieldID)fieldID, isStatic ); } // If clazz represents any class other than the class Object, then this function returns the object that represents the superclass of the class specified by clazz. THREAD_SAFE CUSTOM static IntPtr GetSuperclass(IntPtr clazz) { JNI_PASS_RETV_ARGS( GetSuperclass, (jclass)clazz ); } // Determines whether an object of clazz1 can be safely cast to clazz2. THREAD_SAFE CUSTOM static bool IsAssignableFrom(IntPtr clazz1, IntPtr clazz2) { JNI_PASS_RETV_ARGS( IsAssignableFrom, (jclass)clazz1, (jclass)clazz2 ); } // Causes a java.lang.Throwable object to be thrown. THREAD_SAFE CUSTOM static int Throw(IntPtr obj) { JNI_PASS_RETV_ARGS( Throw, (jthrowable)obj ); } // Constructs an exception object from the specified class with the message specified by message and causes that exception to be thrown. THREAD_SAFE CUSTOM static int ThrowNew(IntPtr clazz, string message) { JNI_PASS_RETV_ARGS( ThrowNew, (jclass)clazz, jStringWrapper(message) ); } // Determines if an exception is being thrown THREAD_SAFE CUSTOM static IntPtr ExceptionOccurred() { JNI_PASS_RETV_VOID( ExceptionOccurred ); } // Prints an exception and a backtrace of the stack to the logcat THREAD_SAFE CUSTOM static void ExceptionDescribe() { JNI_PASS_VOID_VOID( ExceptionDescribe ); } // Clears any exception that is currently being thrown. THREAD_SAFE CUSTOM static void ExceptionClear() { JNI_PASS_VOID_VOID( ExceptionClear ); } // Raises a fatal error and does not expect the VM to recover. This function does not return. THREAD_SAFE CUSTOM static void FatalError(string message) { JNI_PASS_VOID_ARGS( FatalError, jStringWrapper(message) ); } // Creates a new local reference frame, in which at least a given number of local references can be created. THREAD_SAFE CUSTOM static int PushLocalFrame(int capacity) { JNI_PASS_RETV_ARGS( PushLocalFrame, capacity ); } // Pops off the current local reference frame, frees all the local references, and returns a local reference in the previous local reference frame for the given result object. THREAD_SAFE CUSTOM static IntPtr PopLocalFrame(IntPtr result) { JNI_PASS_RETV_ARGS( PopLocalFrame, (jobject)result ); } // Creates a new global reference to the object referred to by the obj argument. THREAD_SAFE CUSTOM static IntPtr NewGlobalRef(IntPtr obj) { JNI_PASS_RETV_ARGS( NewGlobalRef, (jobject)obj ); } // Deletes the global reference pointed to by obj. THREAD_SAFE CUSTOM static void DeleteGlobalRef(IntPtr obj) { JNI_PASS_VOID_ARGS( DeleteGlobalRef, (jobject)obj ); } // Creates a new local reference that refers to the same object as obj. THREAD_SAFE CUSTOM static IntPtr NewLocalRef(IntPtr obj) { JNI_PASS_RETV_ARGS( NewLocalRef, (jobject)obj ); } // Deletes the local reference pointed to by obj. THREAD_SAFE CUSTOM static void DeleteLocalRef(IntPtr obj) { JNI_PASS_VOID_ARGS( DeleteLocalRef, (jobject)obj ); } // Tests whether two references refer to the same Java object. THREAD_SAFE CUSTOM static bool IsSameObject(IntPtr obj1, IntPtr obj2) { JNI_PASS_RETV_ARGS( IsSameObject, (jobject)obj1, (jobject)obj2 ); } // Ensures that at least a given number of local references can be created in the current thread. THREAD_SAFE CUSTOM static int EnsureLocalCapacity(int capacity) { JNI_PASS_RETV_ARGS( EnsureLocalCapacity, capacity ); } //------------------------------------------- // Allocates a new Java object without invoking any of the constructors for the object. THREAD_SAFE CUSTOM static IntPtr AllocObject(IntPtr clazz) { JNI_PASS_RETV_ARGS( AllocObject, (jclass)clazz ); } // Constructs a new Java object. The method ID indicates which constructor method to invoke. This ID must be obtained by calling GetMethodID() with as the method name and void (V) as the return type. THREAD_SAFE CUSTOM static IntPtr NewObject(IntPtr clazz, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( NewObjectA, (jclass)clazz ); } // Returns the class of an object. THREAD_SAFE CUSTOM static IntPtr GetObjectClass(IntPtr obj) { JNI_PASS_RETV_ARGS( GetObjectClass, (jobject)obj ); } // Tests whether an object is an instance of a class. THREAD_SAFE CUSTOM static bool IsInstanceOf(IntPtr obj, IntPtr clazz){ JNI_PASS_RETV_ARGS( IsInstanceOf, (jobject)obj, (jclass)clazz ); } // Returns the method ID for an instance (nonstatic) method of a class or interface. THREAD_SAFE CUSTOM static IntPtr GetMethodID(IntPtr clazz, string name, string sig) { JNI_GET_ID(GetMethodID); } // Returns the field ID for an instance (nonstatic) field of a class. THREAD_SAFE CUSTOM static IntPtr GetFieldID(IntPtr clazz, string name, string sig) { JNI_GET_ID(GetFieldID); } // Returns the method ID for a static method of a class. THREAD_SAFE CUSTOM static IntPtr GetStaticMethodID(IntPtr clazz, string name, string sig) { JNI_GET_ID(GetStaticMethodID); } // Returns the field ID for a static field of a class. THREAD_SAFE CUSTOM static IntPtr GetStaticFieldID(IntPtr clazz, string name, string sig) { JNI_GET_ID(GetStaticFieldID); } // Constructs a new java.lang.String object from an array of characters in modified UTF-8 encoding. THREAD_SAFE CUSTOM static IntPtr NewStringUTF(string bytes) { JNI_PASS_RETV_ARGS( NewStringUTF, jStringWrapper(bytes) ); } // Returns the length in bytes of the modified UTF-8 representation of a string. THREAD_SAFE CUSTOM static int GetStringUTFLength(IntPtr str) { JNI_PASS_RETV_ARGS( GetStringUTFLength, (jstring) str); } // Returns a managed string object representing the string in modified UTF-8 encoding. THREAD_SAFE CUSTOM static string GetStringUTFChars(IntPtr str) { #if UNITY_ANDROID SCOPED_JNI(__FUNCTION__); if (!jni_env) return 0; if (DEBUGJNI) printf_console("> %s()", __FUNCTION__); const char* cstring = jni_env->GetStringUTFChars((jstring)str, 0); if (cstring == 0 || jni_env->ExceptionCheck()) { jni_env->ReleaseStringUTFChars((jstring)str, cstring); return 0; } MonoString* mstring = scripting_string_new(cstring); jni_env->ReleaseStringUTFChars((jstring)str, cstring); return mstring; #else return SCRIPTING_NULL; #endif } //--------------------------------------------- // Calls an instance (nonstatic) Java method defined by methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static string CallStringMethod(IntPtr obj, IntPtr methodID, jvalue[] args) { JNI_CALL_JSTR_METHOD(CallObjectMethodA, (jobject)obj); } // Calls an instance (nonstatic) Java method defined by methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static IntPtr CallObjectMethod(IntPtr obj, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallObjectMethodA, (jobject)obj ); } // Calls an instance (nonstatic) Java method defined by methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static Int32 CallIntMethod(IntPtr obj, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallIntMethodA, (jobject)obj ); } // Calls an instance (nonstatic) Java method defined by methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static bool CallBooleanMethod(IntPtr obj, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallBooleanMethodA, (jobject)obj ); } // Calls an instance (nonstatic) Java method defined by methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static Int16 CallShortMethod(IntPtr obj, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallShortMethodA, (jobject)obj ); } // Calls an instance (nonstatic) Java method defined by methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static Byte CallByteMethod(IntPtr obj, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallByteMethodA, (jobject)obj ); } // Calls an instance (nonstatic) Java method defined by methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static Char CallCharMethod(IntPtr obj, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallCharMethodA, (jobject)obj ); } // Calls an instance (nonstatic) Java method defined by methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static float CallFloatMethod(IntPtr obj, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallFloatMethodA, (jobject)obj ); } // Calls an instance (nonstatic) Java method defined by methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static double CallDoubleMethod(IntPtr obj, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallDoubleMethodA, (jobject)obj ); } // Calls an instance (nonstatic) Java method defined by methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static Int64 CallLongMethod(IntPtr obj, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallLongMethodA, (jobject)obj ); } // Calls an instance (nonstatic) Java method defined by methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static void CallVoidMethod(IntPtr obj, IntPtr methodID, jvalue[] args) { JNI_CALL_VOID_METHOD( CallVoidMethodA, (jobject)obj ); } //--------------------------------------------- // This function returns the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static string GetStringField(IntPtr obj, IntPtr fieldID) { JNI_GET_JSTR_FIELD( GetObjectField, (jobject)obj ); } // This function returns the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static IntPtr GetObjectField(IntPtr obj, IntPtr fieldID) { JNI_GET_FIELD( GetObjectField, (jobject)obj ); } // This function returns the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static bool GetBooleanField(IntPtr obj, IntPtr fieldID) { JNI_GET_FIELD( GetBooleanField, (jobject)obj ); } // This function returns the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static Byte GetByteField(IntPtr obj, IntPtr fieldID) { JNI_GET_FIELD( GetByteField, (jobject)obj ); } // This function returns the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static Char GetCharField(IntPtr obj, IntPtr fieldID) { JNI_GET_FIELD( GetCharField, (jobject)obj ); } // This function returns the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static Int16 GetShortField(IntPtr obj, IntPtr fieldID) { JNI_GET_FIELD( GetShortField, (jobject)obj ); } // This function returns the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static Int32 GetIntField(IntPtr obj, IntPtr fieldID) { JNI_GET_FIELD( GetIntField, (jobject)obj ); } // This function returns the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static Int64 GetLongField(IntPtr obj, IntPtr fieldID) { JNI_GET_FIELD( GetLongField, (jobject)obj ); } // This function returns the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static float GetFloatField(IntPtr obj, IntPtr fieldID) { JNI_GET_FIELD( GetFloatField, (jobject)obj ); } // This function returns the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static double GetDoubleField(IntPtr obj, IntPtr fieldID) { JNI_GET_FIELD( GetDoubleField, (jobject)obj ); } //--------------------------------------------- // This function sets the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static void SetStringField(IntPtr obj, IntPtr fieldID, string val) { JNI_PASS_VOID_ARGS( SetObjectField, (jobject)obj, (jfieldID)fieldID, jStringWrapper(val) ); } // This function sets the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static void SetObjectField(IntPtr obj, IntPtr fieldID, IntPtr val) { JNI_SET_FIELD( SetObjectField, (jobject)obj, (jobject)val ); } // This function sets the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static void SetBooleanField(IntPtr obj, IntPtr fieldID, bool val) { JNI_SET_FIELD( SetBooleanField, (jobject)obj, val ); } // This function sets the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static void SetByteField(IntPtr obj, IntPtr fieldID, Byte val) { JNI_SET_FIELD( SetByteField, (jobject)obj, val ); } // This function sets the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static void SetCharField(IntPtr obj, IntPtr fieldID, Char val) { JNI_SET_FIELD( SetCharField, (jobject)obj, val ); } // This function sets the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static void SetShortField(IntPtr obj, IntPtr fieldID, Int16 val) { JNI_SET_FIELD( SetShortField, (jobject)obj, val ); } // This function sets the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static void SetIntField(IntPtr obj, IntPtr fieldID, Int32 val) { JNI_SET_FIELD( SetIntField, (jobject)obj, val ); } // This function sets the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static void SetLongField(IntPtr obj, IntPtr fieldID, Int64 val) { JNI_SET_FIELD( SetLongField, (jobject)obj, val ); } // This function sets the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static void SetFloatField(IntPtr obj, IntPtr fieldID, float val) { JNI_SET_FIELD( SetFloatField, (jobject)obj, val ); } // This function sets the value of an instance (nonstatic) field of an object. THREAD_SAFE CUSTOM static void SetDoubleField(IntPtr obj, IntPtr fieldID, double val) { JNI_SET_FIELD( SetDoubleField, (jobject)obj, val ); } //--------------------------------------------- // Invokes a static method on a Java object, according to the specified methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static string CallStaticStringMethod(IntPtr clazz, IntPtr methodID, jvalue[] args) { JNI_CALL_JSTR_METHOD(CallStaticObjectMethodA, (jclass)clazz); } // Invokes a static method on a Java object, according to the specified methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static IntPtr CallStaticObjectMethod(IntPtr clazz, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallStaticObjectMethodA, (jclass)clazz ); } // Invokes a static method on a Java object, according to the specified methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static Int32 CallStaticIntMethod(IntPtr clazz, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallStaticIntMethodA, (jclass)clazz ); } // Invokes a static method on a Java object, according to the specified methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static bool CallStaticBooleanMethod(IntPtr clazz, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallStaticBooleanMethodA, (jclass)clazz ); } // Invokes a static method on a Java object, according to the specified methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static Int16 CallStaticShortMethod(IntPtr clazz, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallStaticShortMethodA, (jclass)clazz ); } // Invokes a static method on a Java object, according to the specified methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static Byte CallStaticByteMethod(IntPtr clazz, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallStaticByteMethodA, (jclass)clazz ); } // Invokes a static method on a Java object, according to the specified methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static Char CallStaticCharMethod(IntPtr clazz, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallStaticCharMethodA, (jclass)clazz ); } // Invokes a static method on a Java object, according to the specified methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static float CallStaticFloatMethod(IntPtr clazz, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallStaticFloatMethodA, (jclass)clazz ); } // Invokes a static method on a Java object, according to the specified methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static double CallStaticDoubleMethod(IntPtr clazz, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallStaticDoubleMethodA, (jclass)clazz ); } // Invokes a static method on a Java object, according to the specified methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static Int64 CallStaticLongMethod(IntPtr clazz, IntPtr methodID, jvalue[] args) { JNI_CALL_METHOD( CallStaticLongMethodA, (jclass)clazz ); } // Invokes a static method on a Java object, according to the specified methodID, optionally passing an array of arguments (args) to the method. THREAD_SAFE CUSTOM static void CallStaticVoidMethod(IntPtr clazz, IntPtr methodID, jvalue[] args) { JNI_CALL_VOID_METHOD( CallStaticVoidMethodA, (jclass)clazz ); } //--------------------------------------------- // This function returns the value of a static field of an object. THREAD_SAFE CUSTOM static string GetStaticStringField(IntPtr clazz, IntPtr fieldID) { JNI_GET_JSTR_FIELD( GetStaticObjectField, (jclass)clazz ); } // This function returns the value of a static field of an object. THREAD_SAFE CUSTOM static IntPtr GetStaticObjectField(IntPtr clazz, IntPtr fieldID) { JNI_GET_FIELD( GetStaticObjectField, (jclass)clazz ); } // This function returns the value of a static field of an object. THREAD_SAFE CUSTOM static bool GetStaticBooleanField(IntPtr clazz, IntPtr fieldID) { JNI_GET_FIELD( GetStaticBooleanField, (jclass)clazz ); } // This function returns the value of a static field of an object. THREAD_SAFE CUSTOM static Byte GetStaticByteField(IntPtr clazz, IntPtr fieldID) { JNI_GET_FIELD( GetStaticByteField, (jclass)clazz ); } // This function returns the value of a static field of an object. THREAD_SAFE CUSTOM static Char GetStaticCharField(IntPtr clazz, IntPtr fieldID) { JNI_GET_FIELD( GetStaticCharField, (jclass)clazz ); } // This function returns the value of a static field of an object. THREAD_SAFE CUSTOM static Int16 GetStaticShortField(IntPtr clazz, IntPtr fieldID) { JNI_GET_FIELD( GetStaticShortField, (jclass)clazz ); } // This function returns the value of a static field of an object. THREAD_SAFE CUSTOM static Int32 GetStaticIntField(IntPtr clazz, IntPtr fieldID) { JNI_GET_FIELD( GetStaticIntField, (jclass)clazz ); } // This function returns the value of a static field of an object. THREAD_SAFE CUSTOM static Int64 GetStaticLongField(IntPtr clazz, IntPtr fieldID) { JNI_GET_FIELD( GetStaticLongField, (jclass)clazz ); } // This function returns the value of a static field of an object. THREAD_SAFE CUSTOM static float GetStaticFloatField(IntPtr clazz, IntPtr fieldID) { JNI_GET_FIELD( GetStaticFloatField, (jclass)clazz ); } // This function returns the value of a static field of an object. THREAD_SAFE CUSTOM static double GetStaticDoubleField(IntPtr clazz, IntPtr fieldID) { JNI_GET_FIELD( GetStaticDoubleField, (jclass)clazz ); } //--------------------------------------------- // This function ets the value of a static field of an object. THREAD_SAFE CUSTOM static void SetStaticStringField(IntPtr clazz, IntPtr fieldID, string val) { JNI_PASS_VOID_ARGS( SetStaticObjectField, (jclass)clazz, (jfieldID)fieldID, jStringWrapper(val) ); } // This function ets the value of a static field of an object. THREAD_SAFE CUSTOM static void SetStaticObjectField(IntPtr clazz, IntPtr fieldID, IntPtr val) { JNI_SET_FIELD( SetStaticObjectField, (jclass)clazz, (jclass)val ); } // This function ets the value of a static field of an object. THREAD_SAFE CUSTOM static void SetStaticBooleanField(IntPtr clazz, IntPtr fieldID, bool val) { JNI_SET_FIELD( SetStaticBooleanField, (jclass)clazz, val ); } // This function ets the value of a static field of an object. THREAD_SAFE CUSTOM static void SetStaticByteField(IntPtr clazz, IntPtr fieldID, Byte val) { JNI_SET_FIELD( SetStaticByteField, (jclass)clazz, val ); } // This function ets the value of a static field of an object. THREAD_SAFE CUSTOM static void SetStaticCharField(IntPtr clazz, IntPtr fieldID, Char val) { JNI_SET_FIELD( SetStaticCharField, (jclass)clazz, val ); } // This function ets the value of a static field of an object. THREAD_SAFE CUSTOM static void SetStaticShortField(IntPtr clazz, IntPtr fieldID, Int16 val) { JNI_SET_FIELD( SetStaticShortField, (jclass)clazz, val ); } // This function ets the value of a static field of an object. THREAD_SAFE CUSTOM static void SetStaticIntField(IntPtr clazz, IntPtr fieldID, Int32 val) { JNI_SET_FIELD( SetStaticIntField, (jclass)clazz, val ); } // This function ets the value of a static field of an object. THREAD_SAFE CUSTOM static void SetStaticLongField(IntPtr clazz, IntPtr fieldID, Int64 val) { JNI_SET_FIELD( SetStaticLongField, (jclass)clazz, val ); } // This function ets the value of a static field of an object. THREAD_SAFE CUSTOM static void SetStaticFloatField(IntPtr clazz, IntPtr fieldID, float val) { JNI_SET_FIELD( SetStaticFloatField, (jclass)clazz, val ); } // This function ets the value of a static field of an object. THREAD_SAFE CUSTOM static void SetStaticDoubleField(IntPtr clazz, IntPtr fieldID, double val) { JNI_SET_FIELD( SetStaticDoubleField, (jclass)clazz, val ); } //--------------------------------------- // Convert a managed array of System.Boolean to a Java array of boolean. THREAD_SAFE CUSTOM static IntPtr ToBooleanArray(Boolean[] array) { JNI_NEW_ARRAY( Boolean, jboolean, jbooleanArray );} // Convert a managed array of System.Byte to a Java array of byte. THREAD_SAFE CUSTOM static IntPtr ToByteArray(Byte[] array) { JNI_NEW_ARRAY( Byte, jbyte, jbyteArray ); } // Convert a managed array of System.Char to a Java array of char. THREAD_SAFE CUSTOM static IntPtr ToCharArray(Char[] array) { JNI_NEW_ARRAY( Char, jchar, jcharArray ); } // Convert a managed array of System.Int16 to a Java array of short. THREAD_SAFE CUSTOM static IntPtr ToShortArray(Int16[] array) { JNI_NEW_ARRAY( Short, jshort, jshortArray ); } // Convert a managed array of System.Int32 to a Java array of int. THREAD_SAFE CUSTOM static IntPtr ToIntArray(Int32[] array) { JNI_NEW_ARRAY( Int, jint, jintArray ); } // Convert a managed array of System.Int64 to a Java array of long. THREAD_SAFE CUSTOM static IntPtr ToLongArray(Int64[] array) { JNI_NEW_ARRAY( Long, jlong, jlongArray ); } // Convert a managed array of System.Single to a Java array of float. THREAD_SAFE CUSTOM static IntPtr ToFloatArray(float[] array) { JNI_NEW_ARRAY( Float, jfloat, jfloatArray ); } // Convert a managed array of System.Double to a Java array of double. THREAD_SAFE CUSTOM static IntPtr ToDoubleArray(double[] array) { JNI_NEW_ARRAY( Double, jdouble, jdoubleArray ); } // Convert a managed array of System.IntPtr, representing Java objects, to a Java array of java.lang.Object. THREAD_SAFE CUSTOM static IntPtr ToObjectArray(IntPtr[] array) { #if UNITY_ANDROID SCOPED_JNI(__FUNCTION__); if (!jni_env) return 0; int size = mono_array_length(array); jclass obj_class = jni_env->FindClass("java/lang/Object"); if (obj_class == 0 || jni_env->ExceptionCheck()) return SCRIPTING_NULL; jobjectArray jni_array = jni_env->NewObjectArray(size, obj_class, 0); if (jni_array == 0 || jni_env->ExceptionCheck()) { jni_env->DeleteLocalRef(obj_class); return SCRIPTING_NULL; } for (int i = 0; i < size; ++i) { void* val = GetMonoArrayElement(array, i); jni_env->SetObjectArrayElement(jni_array, i, (jobject)val); jni_env->DeleteLocalRef((jobject) val); if (jni_env->ExceptionCheck()) { jni_env->DeleteLocalRef(jni_array); jni_env->DeleteLocalRef(obj_class); return SCRIPTING_NULL; } } jni_env->DeleteLocalRef(obj_class); return jni_array; #else return 0; #endif } // Convert a Java array of boolean to a managed array of System.Boolean. THREAD_SAFE CUSTOM static Boolean[] FromBooleanArray(IntPtr array) { JNI_GET_ARRAY( Boolean, jboolean, jbooleanArray, mono_get_boolean_class() ); } // Convert a Java array of byte to a managed array of System.Byte. THREAD_SAFE CUSTOM static Byte[] FromByteArray(IntPtr array) { JNI_GET_ARRAY( Byte, jbyte, jbyteArray, mono_get_byte_class() ); } // Convert a Java array of char to a managed array of System.Char. THREAD_SAFE CUSTOM static Char[] FromCharArray(IntPtr array) { JNI_GET_ARRAY( Char, jchar, jcharArray, mono_get_char_class() ); } // Convert a Java array of short to a managed array of System.Int16. THREAD_SAFE CUSTOM static Int16[] FromShortArray(IntPtr array) { JNI_GET_ARRAY( Short, jshort, jshortArray, mono_get_int16_class() ); } // Convert a Java array of int to a managed array of System.Int32. THREAD_SAFE CUSTOM static Int32[] FromIntArray(IntPtr array) { JNI_GET_ARRAY( Int, jint, jintArray, mono_get_int32_class() ); } // Convert a Java array of long to a managed array of System.Int64. THREAD_SAFE CUSTOM static Int64[] FromLongArray(IntPtr array) { JNI_GET_ARRAY( Long, jlong, jlongArray, mono_get_int64_class() ); } // Convert a Java array of float to a managed array of System.Single. THREAD_SAFE CUSTOM static float[] FromFloatArray(IntPtr array) { JNI_GET_ARRAY( Float, jfloat, jfloatArray, mono_get_single_class() ); } // Convert a Java array of double to a managed array of System.Double. THREAD_SAFE CUSTOM static double[] FromDoubleArray(IntPtr array) { JNI_GET_ARRAY( Double, jdouble, jdoubleArray, mono_get_double_class() ); } // Convert a Java array of java.lang.Object to a managed array of System.IntPtr, representing Java objects. THREAD_SAFE CUSTOM static IntPtr[] FromObjectArray(IntPtr array) { #if UNITY_ANDROID SCOPED_JNI(__FUNCTION__); if (!jni_env) return 0; jsize length = jni_env->GetArrayLength((jarray)array); if (jni_env->ExceptionCheck()) return SCRIPTING_NULL; MonoClass* clazz = mono_class_from_name (mono_get_corlib (), "System", "IntPtr"); MonoArray* csarray = mono_array_new(mono_domain_get(), clazz, length); for (int i = 0; i < length; ++i) { jobject obj = jni_env->GetObjectArrayElement((jobjectArray)array, i); if (jni_env->ExceptionCheck()) return SCRIPTING_NULL; Scripting::SetScriptingArrayElement(csarray, i, obj); } return csarray; #else return SCRIPTING_NULL; #endif } // Returns the number of elements in the array. THREAD_SAFE CUSTOM static int GetArrayLength(IntPtr array) { JNI_PASS_RETV_ARGS( GetArrayLength, (jarray) array); } // Construct a new primitive array object. THREAD_SAFE CUSTOM static IntPtr NewBooleanArray(int size) { JNI_PASS_RETV_ARGS( NewBooleanArray, (jsize)size);} // Construct a new primitive array object. THREAD_SAFE CUSTOM static IntPtr NewByteArray(int size) { JNI_PASS_RETV_ARGS( NewByteArray, (jsize)size); } // Construct a new primitive array object. THREAD_SAFE CUSTOM static IntPtr NewCharArray(int size) { JNI_PASS_RETV_ARGS( NewCharArray, (jsize)size); } // Construct a new primitive array object. THREAD_SAFE CUSTOM static IntPtr NewShortArray(int size) { JNI_PASS_RETV_ARGS( NewShortArray, (jsize)size); } // Construct a new primitive array object. THREAD_SAFE CUSTOM static IntPtr NewIntArray(int size) { JNI_PASS_RETV_ARGS( NewIntArray, (jsize)size); } // Construct a new primitive array object. THREAD_SAFE CUSTOM static IntPtr NewLongArray(int size) { JNI_PASS_RETV_ARGS( NewLongArray, (jsize)size); } // Construct a new primitive array object. THREAD_SAFE CUSTOM static IntPtr NewFloatArray(int size) { JNI_PASS_RETV_ARGS( NewFloatArray, (jsize)size); } // Construct a new primitive array object. THREAD_SAFE CUSTOM static IntPtr NewDoubleArray(int size) { JNI_PASS_RETV_ARGS( NewDoubleArray, (jsize)size); } // Constructs a new array holding objects in class clazz. All elements are initially set to obj. THREAD_SAFE CUSTOM static IntPtr NewObjectArray(int size, IntPtr clazz, IntPtr obj) { JNI_PASS_RETV_ARGS( NewObjectArray, (jsize)size, (jclass)clazz, (jobject) obj); } // Returns the value of one element of a primitive array. THREAD_SAFE CUSTOM static bool GetBooleanArrayElement(IntPtr array, int index) { JNI_GET_ARRAY_ELEMENT( Boolean, jboolean, jbooleanArray ); } // Returns the value of one element of a primitive array. THREAD_SAFE CUSTOM static Byte GetByteArrayElement(IntPtr array, int index) { JNI_GET_ARRAY_ELEMENT( Byte, jbyte, jbyteArray ); } // Returns the value of one element of a primitive array. THREAD_SAFE CUSTOM static Char GetCharArrayElement(IntPtr array, int index) { JNI_GET_ARRAY_ELEMENT( Char, jchar, jcharArray ); } // Returns the value of one element of a primitive array. THREAD_SAFE CUSTOM static Int16 GetShortArrayElement(IntPtr array, int index) { JNI_GET_ARRAY_ELEMENT( Short, jshort, jshortArray ); } // Returns the value of one element of a primitive array. THREAD_SAFE CUSTOM static Int32 GetIntArrayElement(IntPtr array, int index) { JNI_GET_ARRAY_ELEMENT( Int, jint, jintArray ); } // Returns the value of one element of a primitive array. THREAD_SAFE CUSTOM static Int64 GetLongArrayElement(IntPtr array, int index) { JNI_GET_ARRAY_ELEMENT( Long, jlong, jlongArray ); } // Returns the value of one element of a primitive array. THREAD_SAFE CUSTOM static float GetFloatArrayElement(IntPtr array, int index) { JNI_GET_ARRAY_ELEMENT( Float, jfloat, jfloatArray ); } // Returns the value of one element of a primitive array. THREAD_SAFE CUSTOM static double GetDoubleArrayElement(IntPtr array, int index) { JNI_GET_ARRAY_ELEMENT( Double, jdouble, jdoubleArray ); } // Returns an element of an Object array. THREAD_SAFE CUSTOM static IntPtr GetObjectArrayElement(IntPtr array, int index) { JNI_PASS_RETV_ARGS( GetObjectArrayElement, (jobjectArray)array, (jsize)index); } // Sets the value of one element in a primitive array. THREAD_SAFE CUSTOM static void SetBooleanArrayElement(IntPtr array, int index, byte val) { JNI_SET_ARRAY_ELEMENT( Boolean, jboolean, jbooleanArray ); } // Sets the value of one element in a primitive array. THREAD_SAFE CUSTOM static void SetByteArrayElement(IntPtr array, int index, sbyte val) { JNI_SET_ARRAY_ELEMENT( Byte, jbyte, jbyteArray ); } // Sets the value of one element in a primitive array. THREAD_SAFE CUSTOM static void SetCharArrayElement(IntPtr array, int index, Char val) { JNI_SET_ARRAY_ELEMENT( Char, jchar, jcharArray ); } // Sets the value of one element in a primitive array. THREAD_SAFE CUSTOM static void SetShortArrayElement(IntPtr array, int index, Int16 val) { JNI_SET_ARRAY_ELEMENT( Short, jshort, jshortArray ); } // Sets the value of one element in a primitive array. THREAD_SAFE CUSTOM static void SetIntArrayElement(IntPtr array, int index, Int32 val) { JNI_SET_ARRAY_ELEMENT( Int, jint, jintArray ); } // Sets the value of one element in a primitive array. THREAD_SAFE CUSTOM static void SetLongArrayElement(IntPtr array, int index, Int64 val) { JNI_SET_ARRAY_ELEMENT( Long, jlong, jlongArray ); } // Sets the value of one element in a primitive array. THREAD_SAFE CUSTOM static void SetFloatArrayElement(IntPtr array, int index, float val) { JNI_SET_ARRAY_ELEMENT( Float, jfloat, jfloatArray ); } // Sets the value of one element in a primitive array. THREAD_SAFE CUSTOM static void SetDoubleArrayElement(IntPtr array, int index, double val) { JNI_SET_ARRAY_ELEMENT( Double, jdouble, jdoubleArray ); } // Sets an element of an Object array. THREAD_SAFE CUSTOM static void SetObjectArrayElement(IntPtr array, int index, IntPtr obj) { JNI_PASS_VOID_ARGS( SetObjectArrayElement, (jobjectArray)array, (jsize)index, (jobject)obj); } END CSRAW } #endif