Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qjnitypes.h
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QJNITYPES_H
5#define QJNITYPES_H
6
7#include <QtCore/qglobal.h>
8
9#if defined(Q_QDOC) || defined(Q_OS_ANDROID)
10
11#include <QtCore/qjnitypes_impl.h>
12#include <QtCore/qjniobject.h>
13#include <QtCore/qjniarray.h>
14
15#if 0
16// This is needed for generating the QtJniTypes forward header
17#pragma qt_class(QtJniTypes)
18#endif
19
20QT_BEGIN_NAMESPACE
21
22#define Q_DECLARE_JNI_TYPE_HELPER(Type) struct
23 Type##Tag { explicit Type##Tag() = default; }; using
24 Type = JObject<Type##Tag>;
25
26// internal - Q_DECLARE_JNI_CLASS is the public macro
27#define Q_DECLARE_JNI_TYPE(Type, Signature) namespace
28 QtJniTypes { Q_DECLARE_JNI_TYPE_HELPER
29 (Type) \
30} template
31 <> struct
32 ::QtJniTypes::Traits<QtJniTypes::Type##Tag> {
33 static constexpr auto signature()
34 {
35 constexpr QtJniTypes::CTString sig(Signature);
36 static_assert((sig.startsWith('L') || sig.startsWith("[L"))
37 && sig.endsWith(';'),
38 "Type signature needs to start with 'L' or"
39 " '[L', and end with ';'");
40 return sig;
41 } \
42};
43
44#define Q_DECLARE_JNI_CLASS_2(Type, _) Q_DECLARE_JNI_TYPE_HELPER
45 (Type)
46
47#define Q_DECLARE_JNI_CLASS_SPECIALIZATION_2(Type, Signature) template
48 <> struct
49 QtJniTypes::Traits<QtJniTypes::Type##Tag> {
50 static constexpr auto className()
51 {
52 return QtJniTypes::CTString(Signature);
53 }
54 static constexpr auto signature()
55 {
56 return QtJniTypes::CTString("L")
57 + className()
58 + QtJniTypes::CTString(";");
59 } \
60};
61
62#define Q_DECLARE_JNI_CLASS_3(NS0, NS1, Type) namespace
63 NS0 { namespace
64 NS1 { Q_DECLARE_JNI_CLASS_2
65 (Type, Q_UNUSED(0)) \
66} \
67}
68
69#define Q_DECLARE_JNI_CLASS_SPECIALIZATION_3(NS0, NS1, Type)
70 Q_DECLARE_JNI_CLASS_SPECIALIZATION_2(NS0::NS1::Type,
71 #NS0 "/" #NS1 "/" #Type)
72
73#define Q_DECLARE_JNI_CLASS_4(NS0, NS1, NS2, Type) namespace
74 NS0 { Q_DECLARE_JNI_CLASS_3
75 (NS1, NS2, Type) \
76}
77
78#define Q_DECLARE_JNI_CLASS_SPECIALIZATION_4(NS0, NS1, NS2, Type)
79 Q_DECLARE_JNI_CLASS_SPECIALIZATION_2(NS0::NS1::NS2::Type,
80 #NS0 "/" #NS1 "/" #NS2 "/" #Type)
81
82#define Q_DECLARE_JNI_CLASS_5(NS0, NS1, NS2, NS3, Type) namespace
83 NS0 { Q_DECLARE_JNI_CLASS_4
84 (NS1, NS2, NS3, Type) \
85}
86
87#define Q_DECLARE_JNI_CLASS_SPECIALIZATION_5(NS0, NS1, NS2, NS3, Type)
88 Q_DECLARE_JNI_CLASS_SPECIALIZATION_2(NS0::NS1::NS2::NS3::Type,
89 #NS0 "/" #NS1 "/" #NS2 "/" #NS3 "/" #Type)
90
91#define Q_DECLARE_JNI_CLASS_6(NS0, NS1, NS2, NS3, NS4, Type) namespace
92 NS0 { Q_DECLARE_JNI_CLASS_5
93 (NS1, NS2, NS3, NS4, Type) \
94}
95
96#define Q_DECLARE_JNI_CLASS_SPECIALIZATION_6(NS0, NS1, NS2, NS3, NS4, Type)
97 Q_DECLARE_JNI_CLASS_SPECIALIZATION_2(NS0::NS1::NS2::NS3::NS4::Type,
98 #NS0 "/" #NS1 "/" #NS2 "/" #NS3 "/" #NS4 "/" #Type)
99
100#define Q_DECLARE_JNI_CLASS_7(NS0, NS1, NS2, NS3, NS4, NS5, Type) namespace
101 NS0 { Q_DECLARE_JNI_CLASS_6
102 (NS1, NS2, NS3, NS4, NS5, Type) \
103}
104
105#define Q_DECLARE_JNI_CLASS_SPECIALIZATION_7(NS0, NS1, NS2, NS3, NS4, NS5, Type)
106 Q_DECLARE_JNI_CLASS_SPECIALIZATION_2(NS0::NS1::NS2::NS3::NS4::NS5::Type,
107 #NS0 "/" #NS1 "/" #NS2 "/" #NS3 "/" #NS4 "/" #NS5 "/" #Type)
108
109#define Q_DECLARE_JNI_CLASS_8(NS0, NS1, NS2, NS3, NS4, NS5, NS6, Type) namespace
110 NS0 { Q_DECLARE_JNI_CLASS_7
111 (NS1, NS2, NS3, NS4, NS5, NS6, Type) \
112}
113
114#define Q_DECLARE_JNI_CLASS_SPECIALIZATION_8(NS0, NS1, NS2, NS3, NS4, NS5, NS6, Type)
115 Q_DECLARE_JNI_CLASS_SPECIALIZATION_2(NS0::NS1::NS2::NS3::NS4::NS5::NS6::Type,
116 #NS0 "/" #NS1 "/" #NS2 "/" #NS3 "/" #NS4 "/" #NS5 "/" #NS6 "/" #Type)
117
118#define Q_DECLARE_JNI_CLASS_9(NS0, NS1, NS2, NS3, NS4, NS5, NS6, NS7, Type) namespace
119 NS0 { Q_DECLARE_JNI_CLASS_8
120 (NS1, NS2, NS3, NS4, NS5, NS6, NS7, Type) \
121}
122
123#define Q_DECLARE_JNI_CLASS_SPECIALIZATION_9(NS0, NS1, NS2, NS3, NS4, NS5, NS6, NS7, Type)
124 Q_DECLARE_JNI_CLASS_SPECIALIZATION_2(NS0::NS1::NS2::NS3::NS4::NS5::NS6::NS7::Type,
125 #NS0 "/" #NS1 "/" #NS2 "/" #NS3 "/" #NS4 "/" #NS5 "/" #NS6 "/" #NS7 "/" #Type)
126
127#define Q_DECLARE_JNI_CLASS(...) namespace
128 QtJniTypes { QT_OVERLOADED_MACRO
129 (Q_DECLARE_JNI_CLASS, __VA_ARGS__) \
130} QT_OVERLOADED_MACRO
131 (Q_DECLARE_JNI_CLASS_SPECIALIZATION, __VA_ARGS__)
132
133// Macros for native methods
134
135namespace QtJniMethods {
136namespace Detail {
137// A helper to forward the call to the registered function (with JNI types
138// as arguments) to the real function, using the type conversion implemented in
139// QJniObject::LocalFrame::convertTo/FromJni. This is needed because we want to
140// write functions that take Qt-style arguments (QJniObject, declared types,
141// QList etc), while Java can only call functions that take jobjects.
142template <typename Arg>
143struct JNITypeForArgImpl
144{
145 using JNIType = decltype(QtJniTypes::Traits<Arg>::convertToJni(nullptr, {}));
146 static Arg fromVarArg(JNIType t) // JNIType is always POD
147 {
148 // Special case: if convertToJni doesn't do anything, don't do anything
149 // here either. convertFromJni would always give us a QJniObject (so
150 // that QJniObject::callMethod etc returns an owning QJniObject).
151 if constexpr (std::is_same_v<JNIType, Arg>) {
152 return t;
153 } else {
154 return QtJniTypes::Traits<Arg>::convertFromJni(t);
155 }
156 }
157};
158
159template <typename Arg>
160using JNITypeForArg = typename JNITypeForArgImpl<std::decay_t<Arg>>::JNIType;
161} // namespace Detail
162} // namespace QtJniMethods
163
164// Declaring a JNI method results in a struct with a template function call() that
165// gets instantiated with the return type and arguments of the declared method,
166// and registered with JNI. That template is implemented to call the declared
167// method, with arguments explicitly converted to the types the declared method
168// expects (e.g. jobject becomes QJniObject, a QString, a QList etc).
169#define Q_DECLARE_JNI_NATIVE_METHOD_HELPER(Method, Postfix, Name) struct
170 Method##_##Postfix { template
171 <typename Ret, typename JType, typename... Args> JNICALL
172 static Ret
173 call(JNIEnv *env, JType thiz, QtJniMethods::Detail::JNITypeForArg<Args> ...args) \
174{
175 return Method(env, thiz, QtJniMethods::Detail::JNITypeForArgImpl<
176 std::decay_t<Args>>::fromVarArg(args)...
177 ); \
178} static
179 constexpr auto signature = QtJniTypes::nativeMethodSignature(Method); template
180 <typename Ret, typename JType, typename ...Args> static
181 constexpr JNINativeMethod makeJNIMethod(Ret(*)(JNIEnv *, JType, Args...)) \
182{
183 return JNINativeMethod {
184 #Name, signature.data(),
185 reinterpret_cast<void *>(&call<Ret, JType, Args...>)
186 }; \
187} \
188};
189
190#define Q_DECLARE_JNI_NATIVE_METHOD(...)
191 QT_OVERLOADED_MACRO(QT_DECLARE_JNI_NATIVE_METHOD, __VA_ARGS__)
192
193#define QT_DECLARE_JNI_NATIVE_METHOD_2(Method, Name) namespace
194 QtJniMethods { Q_DECLARE_JNI_NATIVE_METHOD_HELPER
195 (Method, Helper, Name) \
196}
197
198#define QT_DECLARE_JNI_NATIVE_METHOD_1(Method)
199 QT_DECLARE_JNI_NATIVE_METHOD_2(Method, Method)
200
201#define Q_JNI_NATIVE_METHOD(Method)
202 QtJniMethods::Method##_Helper::makeJNIMethod(QT_PREPEND_NAMESPACE(Method))
203
204#define Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(...)
205 QT_OVERLOADED_MACRO(QT_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE, __VA_ARGS__)
206
207#define QT_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE_2(Method, Name)
208 Q_DECLARE_JNI_NATIVE_METHOD_HELPER(Method, QtJniMethod, Name)
209
210#define QT_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE_1(Method)
211 QT_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE_2(Method, Method)
212
213#define Q_JNI_NATIVE_SCOPED_METHOD(Method, Scope)
214 Scope::Method##_QtJniMethod::makeJNIMethod(Scope::Method)
215
216// Classes for value types
217Q_DECLARE_JNI_CLASS(String, "java/lang/String")
218Q_DECLARE_JNI_CLASS(Integer, "java/lang/Integer");
219Q_DECLARE_JNI_CLASS(Long, "java/lang/Long");
220Q_DECLARE_JNI_CLASS(Double, "java/lang/Double");
221Q_DECLARE_JNI_CLASS(Float, "java/lang/Float");
222Q_DECLARE_JNI_CLASS(Boolean, "java/lang/Boolean");
223Q_DECLARE_JNI_CLASS(Void, "java/lang/Void");
224
225// Utility and I/O
226Q_DECLARE_JNI_CLASS(UUID, "java/util/UUID")
227Q_DECLARE_JNI_CLASS(ArrayList, "java/util/ArrayList")
228Q_DECLARE_JNI_CLASS(HashMap, "java/util/HashMap")
229Q_DECLARE_JNI_CLASS(Set, "java/util/Set")
230Q_DECLARE_JNI_CLASS(File, "java/io/File");
231
232// Android specific types
233Q_DECLARE_JNI_CLASS(Uri, "android/net/Uri");
234Q_DECLARE_JNI_CLASS(Parcelable, "android/os/Parcelable");
235Q_DECLARE_JNI_CLASS(Context, "android/content/Context");
236Q_DECLARE_JNI_CLASS(Intent, "android/content/Intent");
237Q_DECLARE_JNI_CLASS(ContentResolver, "android/content/ContentResolver");
238Q_DECLARE_JNI_CLASS(Activity, "android/app/Activity");
239Q_DECLARE_JNI_CLASS(Service, "android/app/Service");
240
241#define QT_DECLARE_JNI_CLASS_STANDARD_TYPES
242
243QT_END_NAMESPACE
244
245#endif // defined(Q_QDOC) || defined(Q_OS_ANDROID)
246
247#endif // QJNITYPES_H