1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_jni_Types_h__ 8 #define mozilla_jni_Types_h__ 9 10 #include <jni.h> 11 12 #include "mozilla/jni/Refs.h" 13 #include "mozilla/jni/TypeAdapter.h" 14 15 namespace mozilla { 16 namespace jni { 17 namespace detail { 18 19 // TypeAdapter specializations are the interfaces between native/C++ types such 20 // as int32_t and JNI types such as jint. The template parameter T is the native 21 // type, and each TypeAdapter specialization can have the following members: 22 // 23 // * Call: JNIEnv member pointer for making a method call that returns T. 24 // * StaticCall: JNIEnv member pointer for making a static call that returns T. 25 // * Get: JNIEnv member pointer for getting a field of type T. 26 // * StaticGet: JNIEnv member pointer for getting a static field of type T. 27 // * Set: JNIEnv member pointer for setting a field of type T. 28 // * StaticGet: JNIEnv member pointer for setting a static field of type T. 29 // * ToNative: static function that converts the JNI type to the native type. 30 // * FromNative: static function that converts the native type to the JNI type. 31 32 // TypeAdapter<LocalRef<Cls>> applies when jobject is a return value. 33 template <class Cls> 34 struct TypeAdapter<LocalRef<Cls>> { 35 using JNIType = typename Cls::Ref::JNIType; 36 37 static constexpr auto Call = &JNIEnv::CallObjectMethodA; 38 static constexpr auto StaticCall = &JNIEnv::CallStaticObjectMethodA; 39 static constexpr auto Get = &JNIEnv::GetObjectField; 40 static constexpr auto StaticGet = &JNIEnv::GetStaticObjectField; 41 42 // Declare instance as jobject because JNI methods return 43 // jobject even if the return value is really jstring, etc. 44 static LocalRef<Cls> ToNative(JNIEnv* env, jobject instance) { 45 return LocalRef<Cls>::Adopt(env, JNIType(instance)); 46 } 47 48 static JNIType FromNative(JNIEnv*, LocalRef<Cls>&& instance) { 49 return instance.Forget(); 50 } 51 }; 52 53 // clang is picky about function types, including attributes that modify the 54 // calling convention, lining up. GCC appears to be somewhat less so. 55 #ifdef __clang__ 56 # define MOZ_JNICALL_ABI JNICALL 57 #else 58 # define MOZ_JNICALL_ABI 59 #endif 60 61 // NDK r18 made jvalue* method parameters const. We detect the change directly 62 // instead of using ndk-version.h in order to remain compatible with r15 for 63 // now, which doesn't include those headers. 64 class CallArgs { 65 static const jvalue* test(void (JNIEnv::*)(jobject, jmethodID, 66 const jvalue*)); 67 static jvalue* test(void (JNIEnv::*)(jobject, jmethodID, jvalue*)); 68 69 public: 70 using JValueType = decltype(test(&JNIEnv::CallVoidMethodA)); 71 }; 72 73 template <class Cls> 74 constexpr jobject (JNIEnv::*TypeAdapter<LocalRef<Cls>>::Call)( 75 jobject, jmethodID, CallArgs::JValueType) MOZ_JNICALL_ABI; 76 template <class Cls> 77 constexpr jobject (JNIEnv::*TypeAdapter<LocalRef<Cls>>::StaticCall)( 78 jclass, jmethodID, CallArgs::JValueType) MOZ_JNICALL_ABI; 79 template <class Cls> 80 constexpr jobject (JNIEnv::*TypeAdapter<LocalRef<Cls>>::Get)(jobject, jfieldID); 81 template <class Cls> 82 constexpr jobject (JNIEnv::*TypeAdapter<LocalRef<Cls>>::StaticGet)(jclass, 83 jfieldID); 84 85 // TypeAdapter<Ref<Cls>> applies when jobject is a parameter value. 86 template <class Cls, typename T> 87 struct TypeAdapter<Ref<Cls, T>> { 88 using JNIType = typename Ref<Cls, T>::JNIType; 89 90 static constexpr auto Set = &JNIEnv::SetObjectField; 91 static constexpr auto StaticSet = &JNIEnv::SetStaticObjectField; 92 93 static DependentRef<Cls> ToNative(JNIEnv* env, JNIType instance) { 94 return DependentRef<Cls>(instance); 95 } 96 97 static JNIType FromNative(JNIEnv*, const Ref<Cls, T>& instance) { 98 return instance.Get(); 99 } 100 }; 101 102 template <class Cls, typename T> 103 constexpr void (JNIEnv::*TypeAdapter<Ref<Cls, T>>::Set)(jobject, jfieldID, 104 jobject); 105 template <class Cls, typename T> 106 constexpr void (JNIEnv::*TypeAdapter<Ref<Cls, T>>::StaticSet)(jclass, jfieldID, 107 jobject); 108 109 // jstring has its own Param type. 110 template <> 111 struct TypeAdapter<StringParam> : public TypeAdapter<String::Ref> {}; 112 113 template <class Cls> 114 struct TypeAdapter<const Cls&> : public TypeAdapter<Cls> {}; 115 116 } // namespace detail 117 118 using namespace detail; 119 120 } // namespace jni 121 } // namespace mozilla 122 123 #endif // mozilla_jni_Types_h__ 124