summaryrefslogtreecommitdiffstats
path: root/widget/android/jni/Types.h
blob: a083d3e50d0825b70d993bb93e200bae46109a85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#ifndef mozilla_jni_Types_h__
#define mozilla_jni_Types_h__

#include <jni.h>

#include "mozilla/jni/Refs.h"

namespace mozilla {
namespace jni {
namespace detail {

// TypeAdapter specializations are the interfaces between native/C++ types such
// as int32_t and JNI types such as jint. The template parameter T is the native
// type, and each TypeAdapter specialization can have the following members:
//
//  * Call: JNIEnv member pointer for making a method call that returns T.
//  * StaticCall: JNIEnv member pointer for making a static call that returns T.
//  * Get: JNIEnv member pointer for getting a field of type T.
//  * StaticGet: JNIEnv member pointer for getting a static field of type T.
//  * Set: JNIEnv member pointer for setting a field of type T.
//  * StaticGet: JNIEnv member pointer for setting a static field of type T.
//  * ToNative: static function that converts the JNI type to the native type.
//  * FromNative: static function that converts the native type to the JNI type.

template<typename T> struct TypeAdapter;


// TypeAdapter<LocalRef<Cls>> applies when jobject is a return value.
template<class Cls> struct TypeAdapter<LocalRef<Cls>> {
    using JNIType = typename Cls::Ref::JNIType;

    static constexpr auto Call = &JNIEnv::CallObjectMethodA;
    static constexpr auto StaticCall = &JNIEnv::CallStaticObjectMethodA;
    static constexpr auto Get = &JNIEnv::GetObjectField;
    static constexpr auto StaticGet = &JNIEnv::GetStaticObjectField;

    // Declare instance as jobject because JNI methods return
    // jobject even if the return value is really jstring, etc.
    static LocalRef<Cls> ToNative(JNIEnv* env, jobject instance) {
        return LocalRef<Cls>::Adopt(env, JNIType(instance));
    }

    static JNIType FromNative(JNIEnv*, LocalRef<Cls>&& instance) {
        return instance.Forget();
    }
};

// clang is picky about function types, including attributes that modify the calling
// convention, lining up.  GCC appears to be somewhat less so.
#ifdef __clang__
#define MOZ_JNICALL_ABI JNICALL
#else
#define MOZ_JNICALL_ABI
#endif

template<class Cls> constexpr jobject
    (JNIEnv::*TypeAdapter<LocalRef<Cls>>::Call)(jobject, jmethodID, jvalue*) MOZ_JNICALL_ABI;
template<class Cls> constexpr jobject
    (JNIEnv::*TypeAdapter<LocalRef<Cls>>::StaticCall)(jclass, jmethodID, jvalue*) MOZ_JNICALL_ABI;
template<class Cls> constexpr jobject
    (JNIEnv::*TypeAdapter<LocalRef<Cls>>::Get)(jobject, jfieldID);
template<class Cls> constexpr jobject
    (JNIEnv::*TypeAdapter<LocalRef<Cls>>::StaticGet)(jclass, jfieldID);


// TypeAdapter<Ref<Cls>> applies when jobject is a parameter value.
template<class Cls, typename T> struct TypeAdapter<Ref<Cls, T>> {
    using JNIType = typename Ref<Cls, T>::JNIType;

    static constexpr auto Set = &JNIEnv::SetObjectField;
    static constexpr auto StaticSet = &JNIEnv::SetStaticObjectField;

    static DependentRef<Cls> ToNative(JNIEnv* env, JNIType instance) {
        return DependentRef<Cls>(instance);
    }

    static JNIType FromNative(JNIEnv*, const Ref<Cls, T>& instance) {
        return instance.Get();
    }
};

template<class Cls, typename T> constexpr void
    (JNIEnv::*TypeAdapter<Ref<Cls, T>>::Set)(jobject, jfieldID, jobject);
template<class Cls, typename T> constexpr void
    (JNIEnv::*TypeAdapter<Ref<Cls, T>>::StaticSet)(jclass, jfieldID, jobject);


// jstring has its own Param type.
template<> struct TypeAdapter<StringParam>
        : public TypeAdapter<String::Ref>
{};

template<class Cls> struct TypeAdapter<const Cls&>
        : public TypeAdapter<Cls>
{};


#define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName) \
    \
    template<> struct TypeAdapter<NativeType> { \
        using JNI##Type = JNIType; \
    \
        static constexpr auto Call = &JNIEnv::Call ## JNIName ## MethodA; \
        static constexpr auto StaticCall = &JNIEnv::CallStatic ## JNIName ## MethodA; \
        static constexpr auto Get = &JNIEnv::Get ## JNIName ## Field; \
        static constexpr auto StaticGet = &JNIEnv::GetStatic ## JNIName ## Field; \
        static constexpr auto Set = &JNIEnv::Set ## JNIName ## Field; \
        static constexpr auto StaticSet = &JNIEnv::SetStatic ## JNIName ## Field; \
        static constexpr auto GetArray = &JNIEnv::Get ## JNIName ## ArrayRegion; \
        static constexpr auto SetArray = &JNIEnv::Set ## JNIName ## ArrayRegion; \
        static constexpr auto NewArray = &JNIEnv::New ## JNIName ## Array; \
    \
        static JNIType FromNative(JNIEnv*, NativeType val) { \
            return static_cast<JNIType>(val); \
        } \
        static NativeType ToNative(JNIEnv*, JNIType val) { \
            return static_cast<NativeType>(val); \
        } \
    }


DEFINE_PRIMITIVE_TYPE_ADAPTER(bool,     jboolean, Boolean);
DEFINE_PRIMITIVE_TYPE_ADAPTER(int8_t,   jbyte,    Byte);
DEFINE_PRIMITIVE_TYPE_ADAPTER(char16_t, jchar,    Char);
DEFINE_PRIMITIVE_TYPE_ADAPTER(int16_t,  jshort,   Short);
DEFINE_PRIMITIVE_TYPE_ADAPTER(int32_t,  jint,     Int);
DEFINE_PRIMITIVE_TYPE_ADAPTER(int64_t,  jlong,    Long);
DEFINE_PRIMITIVE_TYPE_ADAPTER(float,    jfloat,   Float);
DEFINE_PRIMITIVE_TYPE_ADAPTER(double,   jdouble,  Double);

#undef DEFINE_PRIMITIVE_TYPE_ADAPTER

} // namespace detail

using namespace detail;

} // namespace jni
} // namespace mozilla

#endif // mozilla_jni_Types_h__