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