Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qjniobject.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 QJNIOBJECT_H
5#define QJNIOBJECT_H
6
7#include <QtCore/qsharedpointer.h>
8
9#if defined(Q_QDOC) || defined(Q_OS_ANDROID)
10#include <jni.h>
11#include <QtCore/qjnienvironment.h>
12
14
16
17class Q_CORE_EXPORT QJniObject
18{
19 friend class QJniArrayBase;
20
21 template <typename ...Args>
22 struct LocalFrame {
23 mutable JNIEnv *env;
24 bool hasFrame = false;
25 explicit LocalFrame(JNIEnv *env = nullptr) noexcept
26 : env(env)
27 {
28 }
29 ~LocalFrame()
30 {
31 if (hasFrame)
32 env->PopLocalFrame(nullptr);
33 }
34 template <typename T>
35 auto newLocalRef(jobject object)
36 {
37 if (!hasFrame) {
38 if (jniEnv()->PushLocalFrame(sizeof...(Args)) < 0)
39 return T{}; // JVM is out of memory, avoid making matters worse
40 hasFrame = true;
41 }
42 return static_cast<T>(jniEnv()->NewLocalRef(object));
43 }
44 template <typename T>
45 auto newLocalRef(const QJniObject &object)
46 {
47 return newLocalRef<T>(object.template object<T>());
48 }
49 JNIEnv *jniEnv() const
50 {
51 if (!env)
52 env = QJniEnvironment::getJniEnv();
53 return env;
54 }
55 bool checkAndClearExceptions()
56 {
57 return env ? QJniEnvironment::checkAndClearExceptions(env) : false;
58 }
59 template <typename T>
60 auto convertToJni(T &&value);
61 template <typename T>
62 auto convertFromJni(QJniObject &&object);
63 };
64public:
65 QJniObject();
66 explicit QJniObject(const char *className);
67 explicit QJniObject(const char *className, const char *signature, ...);
68 template<typename ...Args
69#ifndef Q_QDOC
70 , std::enable_if_t<!std::disjunction_v<QtJniTypes::IsStringType<std::decay_t<Args>>...>>* = nullptr
71#endif
72 >
73 explicit QJniObject(const char *className, Args &&...args)
74 : QJniObject(LocalFrame<Args...>{}, className, std::forward<Args>(args)...)
75 {
76 }
77private:
78 template<typename ...Args>
79 explicit QJniObject(LocalFrame<Args...> localFrame, const char *className, Args &&...args)
80 : QJniObject(className, QtJniTypes::constructorSignature<Args...>().data(),
81 localFrame.convertToJni(std::forward<Args>(args))...)
82 {
83 }
84public:
85 explicit QJniObject(jclass clazz);
86 explicit QJniObject(jclass clazz, const char *signature, ...);
87 template<typename ...Args
88#ifndef Q_QDOC
89 , std::enable_if_t<!std::disjunction_v<QtJniTypes::IsStringType<std::decay_t<Args>>...>>* = nullptr
90#endif
91 >
92 explicit QJniObject(jclass clazz, Args &&...args)
93 : QJniObject(clazz, QtJniTypes::constructorSignature<Args...>().data(),
94 std::forward<Args>(args)...)
95 {}
96 QJniObject(jobject globalRef);
97
98 QJniObject(const QJniObject &other) noexcept = default;
99 QJniObject(QJniObject &&other) noexcept = default;
100 QJniObject &operator=(const QJniObject &other) noexcept = default;
101 QJniObject &operator=(QJniObject &&other) noexcept = default;
102
103 ~QJniObject();
104
105 template<typename Class, typename ...Args>
106 static inline QJniObject construct(Args &&...args)
107 {
108 LocalFrame<Args...> frame;
109 return QJniObject(QtJniTypes::Traits<Class>::className().data(),
110 QtJniTypes::constructorSignature<Args...>().data(),
111 frame.convertToJni(std::forward<Args>(args))...);
112 }
113
114 jobject object() const;
115 template <typename T> T object() const
116 {
117 QtJniTypes::assertObjectType<T>();
118 return static_cast<T>(javaObject());
119 }
120
121 jclass objectClass() const;
122 QByteArray className() const;
123
124 template <typename Ret, typename ...Args
125#ifndef Q_QDOC
126 , QtJniTypes::IfValidFieldType<Ret> = true
127#endif
128 >
129 auto callMethod(const char *methodName, const char *signature, Args &&...args) const
130 {
131 LocalFrame<Args...> frame(jniEnv());
132 if constexpr (QtJniTypes::isObjectType<Ret>()) {
133 return frame.template convertFromJni<Ret>(callObjectMethod(methodName, signature,
134 frame.convertToJni(std::forward<Args>(args))...));
135 } else {
136 jmethodID id = getCachedMethodID(frame.jniEnv(), methodName, signature);
137 if (id) {
138 if constexpr (std::is_same_v<Ret, void>) {
139 callVoidMethodV(frame.jniEnv(), id,
140 frame.convertToJni(std::forward<Args>(args))...);
141 frame.checkAndClearExceptions();
142 } else {
143 Ret res{};
144 callMethodForType<Ret>(frame.jniEnv(), res, object(), id,
145 frame.convertToJni(std::forward<Args>(args))...);
146 if (frame.checkAndClearExceptions())
147 res = {};
148 return res;
149 }
150 }
151 if constexpr (!std::is_same_v<Ret, void>)
152 return Ret{};
153 }
154 }
155
156 template <typename Ret, typename ...Args
157#ifndef Q_QDOC
158 , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
159#endif
160 >
161 auto callMethod(const char *methodName, Args &&...args) const
162 {
163 constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
164 return callMethod<Ret>(methodName, signature.data(), std::forward<Args>(args)...);
165 }
166
167 template <typename Ret, typename ...Args
168#ifndef Q_QDOC
169 , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
170#endif
171 >
172 QJniObject callObjectMethod(const char *methodName, Args &&...args) const
173 {
174 QtJniTypes::assertObjectType<Ret>();
175 constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
176 LocalFrame<Args...> frame(jniEnv());
177 return frame.template convertFromJni<Ret>(callObjectMethod(methodName, signature,
178 frame.convertToJni(std::forward<Args>(args))...));
179 }
180
181 QJniObject callObjectMethod(const char *methodName, const char *signature, ...) const;
182
183 template <typename Ret, typename ...Args>
184 static auto callStaticMethod(const char *className, const char *methodName, const char *signature, Args &&...args)
185 {
186 JNIEnv *env = QJniEnvironment::getJniEnv();
187 jclass clazz = QJniObject::loadClass(className, env);
188 return callStaticMethod<Ret>(clazz, methodName, signature, std::forward<Args>(args)...);
189 }
190
191 template <typename Ret, typename ...Args>
192 static auto callStaticMethod(jclass clazz, const char *methodName, const char *signature, Args &&...args)
193 {
194 JNIEnv *env = QJniEnvironment::getJniEnv();
195 jmethodID id = clazz ? getMethodID(env, clazz, methodName, signature, true)
196 : 0;
197 return callStaticMethod<Ret>(clazz, id, std::forward<Args>(args)...);
198 }
199
200 template <typename Ret, typename ...Args
201#ifndef Q_QDOC
202 , QtJniTypes::IfValidFieldType<Ret> = true
203#endif
204 >
205 static auto callStaticMethod(jclass clazz, jmethodID methodId, Args &&...args)
206 {
207 LocalFrame<Args...> frame;
208 if constexpr (QtJniTypes::isObjectType<Ret>()) {
209 return frame.template convertFromJni<Ret>(callStaticObjectMethod(clazz, methodId,
210 frame.convertToJni(std::forward<Args>(args))...));
211 } else {
212 if (clazz && methodId) {
213 if constexpr (std::is_same_v<Ret, void>) {
214 callStaticMethodForVoid(frame.jniEnv(), clazz, methodId,
215 frame.convertToJni(std::forward<Args>(args))...);
216 frame.checkAndClearExceptions();
217 } else {
218 Ret res{};
219 callStaticMethodForType<Ret>(frame.jniEnv(), res, clazz, methodId,
220 frame.convertToJni(std::forward<Args>(args))...);
221 if (frame.checkAndClearExceptions())
222 res = {};
223 return res;
224 }
225 }
226 if constexpr (!std::is_same_v<Ret, void>)
227 return Ret{};
228 }
229 }
230
231 template <typename Ret, typename ...Args
232#ifndef Q_QDOC
233 , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
234#endif
235 >
236 static auto callStaticMethod(const char *className, const char *methodName, Args &&...args)
237 {
238 JNIEnv *env = QJniEnvironment::getJniEnv();
239 jclass clazz = QJniObject::loadClass(className, env);
240 const jmethodID id = clazz ? getMethodID(env, clazz, methodName,
241 QtJniTypes::methodSignature<Ret, Args...>().data(), true)
242 : 0;
243 return callStaticMethod<Ret>(clazz, id, std::forward<Args>(args)...);
244 }
245
246 template <typename Ret, typename ...Args
247#ifndef Q_QDOC
248 , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
249#endif
250 >
251 static auto callStaticMethod(jclass clazz, const char *methodName, Args &&...args)
252 {
253 constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
254 return callStaticMethod<Ret>(clazz, methodName, signature.data(), std::forward<Args>(args)...);
255 }
256 template <typename Klass, typename Ret, typename ...Args
257#ifndef Q_QDOC
258 , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
259#endif
260 >
261 static auto callStaticMethod(const char *methodName, Args &&...args)
262 {
263 JNIEnv *env = QJniEnvironment::getJniEnv();
264 const jclass clazz = QJniObject::loadClass(QtJniTypes::Traits<Klass>::className().data(),
265 env);
266 const jmethodID id = clazz ? getMethodID(env, clazz, methodName,
267 QtJniTypes::methodSignature<Ret, Args...>().data(), true)
268 : 0;
269 return callStaticMethod<Ret>(clazz, id, std::forward<Args>(args)...);
270 }
271
272 static QJniObject callStaticObjectMethod(const char *className, const char *methodName,
273 const char *signature, ...);
274
275 static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName,
276 const char *signature, ...);
277
278 static QJniObject callStaticObjectMethod(jclass clazz, jmethodID methodId, ...);
279
280
281 template <typename Ret, typename ...Args
282#ifndef Q_QDOC
283 , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
284#endif
285 >
286 static QJniObject callStaticObjectMethod(const char *className, const char *methodName, Args &&...args)
287 {
288 QtJniTypes::assertObjectType<Ret>();
289 constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
290 LocalFrame<Args...> frame;
291 return frame.template convertFromJni<Ret>(callStaticObjectMethod(className, methodName, signature.data(),
292 frame.convertToJni(std::forward<Args>(args))...));
293 }
294
295 template <typename Ret, typename ...Args
296#ifndef Q_QDOC
297 , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
298#endif
299 >
300 static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName, Args &&...args)
301 {
302 QtJniTypes::assertObjectType<Ret>();
303 constexpr auto signature = QtJniTypes::methodSignature<Ret, Args...>();
304 LocalFrame<Args...> frame;
305 return frame.template convertFromJni<Ret>(callStaticObjectMethod(clazz, methodName, signature.data(),
306 frame.convertToJni(std::forward<Args>(args))...));
307 }
308
309 template <typename T
310#ifndef Q_QDOC
311 , QtJniTypes::IfValidFieldType<T> = true
312#endif
313 >
314 auto getField(const char *fieldName) const
315 {
316 LocalFrame<T> frame(jniEnv());
317 if constexpr (QtJniTypes::isObjectType<T>()) {
318 return frame.template convertFromJni<T>(getObjectField<T>(fieldName));
319 } else {
320 T res{};
321 constexpr auto signature = QtJniTypes::fieldSignature<T>();
322 jfieldID id = getCachedFieldID(frame.jniEnv(), fieldName, signature);
323 if (id) {
324 getFieldForType<T>(frame.jniEnv(), res, object(), id);
325 if (frame.checkAndClearExceptions())
326 res = {};
327 }
328 return res;
329 }
330 }
331
332 template <typename T
333#ifndef Q_QDOC
334 , QtJniTypes::IfValidFieldType<T> = true
335#endif
336 >
337 static auto getStaticField(const char *className, const char *fieldName)
338 {
339 LocalFrame<T> frame;
340 if constexpr (QtJniTypes::isObjectType<T>()) {
341 return frame.template convertFromJni<T>(getStaticObjectField<T>(className, fieldName));
342 } else {
343 jclass clazz = QJniObject::loadClass(className, frame.jniEnv());
344 if (!clazz)
345 return T{};
346 return getStaticField<T>(clazz, fieldName);
347 }
348 }
349
350 template <typename T
351#ifndef Q_QDOC
352 , QtJniTypes::IfValidFieldType<T> = true
353#endif
354 >
355 static auto getStaticField(jclass clazz, const char *fieldName)
356 {
357 LocalFrame<T> frame;
358 if constexpr (QtJniTypes::isObjectType<T>()) {
359 return frame.template convertFromJni<T>(getStaticObjectField<T>(clazz, fieldName));
360 } else {
361 T res{};
362 constexpr auto signature = QtJniTypes::fieldSignature<T>();
363 jfieldID id = getFieldID(frame.jniEnv(), clazz, fieldName, signature, true);
364 if (id) {
365 getStaticFieldForType<T>(frame.jniEnv(), res, clazz, id);
366 if (frame.checkAndClearExceptions())
367 res = {};
368 }
369 return res;
370 }
371 }
372
373 template <typename Klass, typename T
374#ifndef Q_QDOC
375 , QtJniTypes::IfValidFieldType<T> = true
376#endif
377 >
378 static auto getStaticField(const char *fieldName)
379 {
380 return getStaticField<T>(QtJniTypes::Traits<Klass>::className(), fieldName);
381 }
382
383 template <typename T
384#ifndef Q_QDOC
385 , std::enable_if_t<QtJniTypes::isObjectType<T>(), bool> = true
386#endif
387 >
388 QJniObject getObjectField(const char *fieldName) const
389 {
390 constexpr auto signature = QtJniTypes::fieldSignature<T>();
391 return getObjectField(fieldName, signature);
392 }
393
394 QJniObject getObjectField(const char *fieldName, const char *signature) const;
395
396 template <typename T
397#ifndef Q_QDOC
398 , std::enable_if_t<QtJniTypes::isObjectType<T>(), bool> = true
399#endif
400 >
401 static QJniObject getStaticObjectField(const char *className, const char *fieldName)
402 {
403 constexpr auto signature = QtJniTypes::fieldSignature<T>();
404 return getStaticObjectField(className, fieldName, signature);
405 }
406
407 static QJniObject getStaticObjectField(const char *className,
408 const char *fieldName,
409 const char *signature);
410
411 template <typename T
412#ifndef Q_QDOC
413 , std::enable_if_t<QtJniTypes::isObjectType<T>(), bool> = true
414#endif
415 >
416 static QJniObject getStaticObjectField(jclass clazz, const char *fieldName)
417 {
418 constexpr auto signature = QtJniTypes::fieldSignature<T>();
419 return getStaticObjectField(clazz, fieldName, signature);
420 }
421
422 static QJniObject getStaticObjectField(jclass clazz, const char *fieldName,
423 const char *signature);
424
425 template <typename T
426#ifndef Q_QDOC
427 , QtJniTypes::IfValidFieldType<T> = true
428#endif
429 >
430 void setField(const char *fieldName, T value)
431 {
432 constexpr auto signature = QtJniTypes::fieldSignature<T>();
433 jfieldID id = getCachedFieldID(jniEnv(), fieldName, signature);
434 if (id) {
435 setFieldForType<T>(jniEnv(), object(), id, value);
436 QJniEnvironment::checkAndClearExceptions(jniEnv());
437 }
438 }
439
440 template <typename T
441#ifndef Q_QDOC
442 , QtJniTypes::IfValidFieldType<T> = true
443#endif
444 >
445 void setField(const char *fieldName, const char *signature, T value)
446 {
447 jfieldID id = getCachedFieldID(jniEnv(), fieldName, signature);
448 if (id) {
449 setFieldForType<T>(jniEnv(), object(), id, value);
450 QJniEnvironment::checkAndClearExceptions(jniEnv());
451 }
452 }
453
454 template <typename T
455#ifndef Q_QDOC
456 , QtJniTypes::IfValidFieldType<T> = true
457#endif
458 >
459 static void setStaticField(const char *className, const char *fieldName, T value)
460 {
461 LocalFrame<T> frame;
462 jclass clazz = QJniObject::loadClass(className, frame.jniEnv());
463 if (!clazz)
464 return;
465
466 constexpr auto signature = QtJniTypes::fieldSignature<T>();
467 jfieldID id = getCachedFieldID(frame.jniEnv(), clazz, className, fieldName,
468 signature, true);
469 if (!id)
470 return;
471
472 setStaticFieldForType<T>(frame.jniEnv(), clazz, id, value);
473 frame.checkAndClearExceptions();
474 }
475
476 template <typename T
477#ifndef Q_QDOC
478 , QtJniTypes::IfValidFieldType<T> = true
479#endif
480 >
481 static void setStaticField(const char *className, const char *fieldName,
482 const char *signature, T value)
483 {
484 JNIEnv *env = QJniEnvironment::getJniEnv();
485 jclass clazz = QJniObject::loadClass(className, env);
486
487 if (!clazz)
488 return;
489
490 jfieldID id = getCachedFieldID(env, clazz, className, fieldName,
491 signature, true);
492 if (id) {
493 setStaticFieldForType<T>(env, clazz, id, value);
494 QJniEnvironment::checkAndClearExceptions(env);
495 }
496 }
497
498 template <typename T
499#ifndef Q_QDOC
500 , QtJniTypes::IfValidFieldType<T> = true
501#endif
502 >
503 static void setStaticField(jclass clazz, const char *fieldName,
504 const char *signature, T value)
505 {
506 JNIEnv *env = QJniEnvironment::getJniEnv();
507 jfieldID id = getFieldID(env, clazz, fieldName, signature, true);
508
509 if (id) {
510 setStaticFieldForType<T>(env, clazz, id, value);
511 QJniEnvironment::checkAndClearExceptions(env);
512 }
513 }
514
515 template <typename T
516#ifndef Q_QDOC
517 , QtJniTypes::IfValidFieldType<T> = true
518#endif
519 >
520 static void setStaticField(jclass clazz, const char *fieldName, T value)
521 {
522 setStaticField(clazz, fieldName, QtJniTypes::fieldSignature<T>(), value);
523 }
524
525 template <typename Klass, typename T
526#ifndef Q_QDOC
527 , QtJniTypes::IfValidFieldType<T> = true
528#endif
529 >
530 static void setStaticField(const char *fieldName, T value)
531 {
532 setStaticField(QtJniTypes::Traits<Klass>::className(), fieldName, value);
533 }
534
535 static QJniObject fromString(const QString &string);
536 QString toString() const;
537
538 static bool isClassAvailable(const char *className);
539 bool isValid() const;
540
541 // This function takes ownership of the jobject and releases the local ref. before returning.
542 static QJniObject fromLocalRef(jobject lref);
543
544 template <typename T,
545 std::enable_if_t<std::is_convertible_v<T, jobject>, bool> = true>
546 QJniObject &operator=(T obj)
547 {
548 assign(static_cast<T>(obj));
549 return *this;
550 }
551
552protected:
554 JNIEnv *jniEnv() const noexcept;
555
556private:
557 static jclass loadClass(const QByteArray &className, JNIEnv *env);
558
559#if QT_CORE_REMOVED_SINCE(6, 7)
560 // these need to stay in the ABI as they were used in inline methods before 6.7
561 static jclass loadClass(const QByteArray &className, JNIEnv *env, bool binEncoded);
562 static QByteArray toBinaryEncClassName(const QByteArray &className);
563 void callVoidMethodV(JNIEnv *env, jmethodID id, va_list args) const;
564#endif
565
566 static jfieldID getCachedFieldID(JNIEnv *env, jclass clazz, const QByteArray &className,
567 const char *name, const char *signature,
568 bool isStatic = false);
569 jfieldID getCachedFieldID(JNIEnv *env, const char *name, const char *signature,
570 bool isStatic = false) const;
571 static jmethodID getCachedMethodID(JNIEnv *env, jclass clazz, const QByteArray &className,
572 const char *name, const char *signature,
573 bool isStatic = false);
574 jmethodID getCachedMethodID(JNIEnv *env, const char *name, const char *signature,
575 bool isStatic = false) const;
576
577 static jfieldID getFieldID(JNIEnv *env, jclass clazz, const char *name,
578 const char *signature, bool isStatic = false);
579 static jmethodID getMethodID(JNIEnv *env, jclass clazz, const char *name,
580 const char *signature, bool isStatic = false);
581
582 void callVoidMethodV(JNIEnv *env, jmethodID id, ...) const;
583
584 bool isSameObject(jobject obj) const;
585 bool isSameObject(const QJniObject &other) const;
586 void assign(jobject obj);
587 jobject javaObject() const;
588
589 friend bool operator==(const QJniObject &, const QJniObject &);
590 friend bool operator!=(const QJniObject&, const QJniObject&);
591
592 template<typename T>
593 static constexpr void callMethodForType(JNIEnv *env, T &res, jobject obj, jmethodID id, ...)
594 {
595 va_list args = {};
596 va_start(args, id);
597 QtJniTypes::Caller<T>::callMethodForType(env, res, obj, id, args);
598 va_end(args);
599 }
600
601 template<typename T>
602 static constexpr void callStaticMethodForType(JNIEnv *env, T &res, jclass clazz,
603 jmethodID id, ...)
604 {
605 if (!clazz || !id)
606 return;
607 va_list args = {};
608 va_start(args, id);
609 QtJniTypes::Caller<T>::callStaticMethodForType(env, res, clazz, id, args);
610 va_end(args);
611 }
612
613 static void callStaticMethodForVoid(JNIEnv *env, jclass clazz, jmethodID id, ...)
614 {
615 if (!clazz || !id)
616 return;
617 va_list args;
618 va_start(args, id);
619 env->CallStaticVoidMethodV(clazz, id, args);
620 va_end(args);
621 }
622
623
624 template<typename T>
625 static constexpr void getFieldForType(JNIEnv *env, T &res, jobject obj, jfieldID id)
626 {
627 QtJniTypes::Caller<T>::getFieldForType(env, res, obj, id);
628 }
629
630 template<typename T>
631 static constexpr void getStaticFieldForType(JNIEnv *env, T &res, jclass clazz, jfieldID id)
632 {
633 QtJniTypes::Caller<T>::getStaticFieldForType(env, res, clazz, id);
634 }
635
636 template<typename T>
637 static constexpr void setFieldForType(JNIEnv *env, jobject obj, jfieldID id, T value)
638 {
639 if constexpr (QtJniTypes::isObjectType<T>()) {
640 LocalFrame<T> frame(env);
641 env->SetObjectField(obj, id, static_cast<jobject>(frame.convertToJni(value)));
642 } else {
643 QtJniTypes::Caller<T>::setFieldForType(env, obj, id, value);
644 }
645 }
646
647 template<typename T>
648 static constexpr void setStaticFieldForType(JNIEnv *env, jclass clazz, jfieldID id, T value)
649 {
650 if constexpr (QtJniTypes::isObjectType<T>()) {
651 LocalFrame<T> frame(env);
652 env->SetStaticObjectField(clazz, id, static_cast<jobject>(frame.convertToJni(value)));
653 } else {
654 QtJniTypes::Caller<T>::setStaticFieldForType(env, clazz, id, value);
655 }
656 }
657
658 friend QJniObjectPrivate;
659 QSharedPointer<QJniObjectPrivate> d;
660};
661
662inline bool operator==(const QJniObject &obj1, const QJniObject &obj2)
663{
664 return obj1.isSameObject(obj2);
665}
666
667inline bool operator!=(const QJniObject &obj1, const QJniObject &obj2)
668{
669 return !obj1.isSameObject(obj2);
670}
671
672namespace QtJniTypes {
673struct QT_TECH_PREVIEW_API JObjectBase
674{
675 operator QJniObject() const { return m_object; }
676
677 bool isValid() const { return m_object.isValid(); }
678 jclass objectClass() const { return m_object.objectClass(); }
679 QString toString() const { return m_object.toString(); }
680
681 template <typename T = jobject>
682 T object() const {
683 return m_object.object<T>();
684 }
685
686protected:
687 JObjectBase() = default;
688 ~JObjectBase() = default;
689
690 Q_IMPLICIT JObjectBase(jobject object) : m_object(object) {}
691 Q_IMPLICIT JObjectBase(const QJniObject &object) : m_object(object) {}
692 Q_IMPLICIT JObjectBase(QJniObject &&object) noexcept : m_object(std::move(object)) {}
693
694 QJniObject m_object;
695};
696
697template<typename Type>
698class QT_TECH_PREVIEW_API JObject : public JObjectBase
699{
700public:
701 using Class = Type;
702
703 JObject()
704 : JObjectBase{QJniObject(QtJniTypes::Traits<Class>::className())}
705 {}
706 Q_IMPLICIT JObject(jobject object) : JObjectBase(object) {}
707 Q_IMPLICIT JObject(const QJniObject &object) : JObjectBase(object) {}
708 Q_IMPLICIT JObject(QJniObject &&object) noexcept : JObjectBase(std::move(object)) {}
709
710 // base class destructor is protected, so need to provide all SMFs
711 JObject(const JObject &other) = default;
712 JObject(JObject &&other) noexcept = default;
713 JObject &operator=(const JObject &other) = default;
714 JObject &operator=(JObject &&other) noexcept = default;
715
716 ~JObject() = default;
717
718 template<typename Arg, typename ...Args
719 , std::enable_if_t<!std::is_same_v<Arg, JObject>, bool> = true
720 , IfValidSignatureTypes<Arg, Args...> = true
721 >
722 explicit JObject(Arg && arg, Args &&...args)
723 : JObjectBase{QJniObject(QtJniTypes::Traits<Class>::className(),
724 std::forward<Arg>(arg), std::forward<Args>(args)...)}
725 {}
726
727 // named constructors avoid ambiguities
728 static Type fromJObject(jobject object) { return Type(object); }
729 template <typename ...Args>
730 static Type construct(Args &&...args) { return Type(std::forward<Args>(args)...); }
731 static Type fromLocalRef(jobject lref) { return Type(QJniObject::fromLocalRef(lref)); }
732
733 static bool registerNativeMethods(std::initializer_list<JNINativeMethod> methods)
734 {
735 QJniEnvironment env;
736 return env.registerNativeMethods<Class>(methods);
737 }
738
739 // public API forwarding to QJniObject, with the implicit Class template parameter
740 template <typename Ret, typename ...Args
741#ifndef Q_QDOC
742 , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
743#endif
744 >
745 static auto callStaticMethod(const char *name, Args &&...args)
746 {
747 return QJniObject::callStaticMethod<Class, Ret, Args...>(name,
748 std::forward<Args>(args)...);
749 }
750 template <typename T
751#ifndef Q_QDOC
752 , QtJniTypes::IfValidFieldType<T> = true
753#endif
754 >
755 static auto getStaticField(const char *field)
756 {
757 return QJniObject::getStaticField<Class, T>(field);
758 }
759 template <typename T
760#ifndef Q_QDOC
761 , QtJniTypes::IfValidFieldType<T> = true
762#endif
763 >
764 static void setStaticField(const char *field, T &&value)
765 {
766 QJniObject::setStaticField<Class, T>(field, std::forward<T>(value));
767 }
768
769 // keep only these overloads, the rest is made private
770 template <typename Ret, typename ...Args
771#ifndef Q_QDOC
772 , QtJniTypes::IfValidSignatureTypes<Ret, Args...> = true
773#endif
774 >
775 auto callMethod(const char *method, Args &&...args) const
776 {
777 return m_object.callMethod<Ret>(method, std::forward<Args>(args)...);
778 }
779 template <typename T
780#ifndef Q_QDOC
781 , QtJniTypes::IfValidFieldType<T> = true
782#endif
783 >
784 auto getField(const char *fieldName) const
785 {
786 return m_object.getField<T>(fieldName);
787 }
788
789 template <typename T
790#ifndef Q_QDOC
791 , QtJniTypes::IfValidFieldType<T> = true
792#endif
793 >
794 void setField(const char *fieldName, T &&value)
795 {
796 m_object.setField(fieldName, std::forward<T>(value));
797 }
798
799 QByteArray className() const {
800 return QtJniTypes::Traits<Class>::className().data();
801 }
802
803private:
804 friend bool comparesEqual(const JObject &lhs, const JObject &rhs) noexcept
805 { return lhs.m_object == rhs.m_object; }
807};
808}
809
810// This cannot be included earlier as QJniArray is a QJniObject subclass, but it
811// must be included so that we can implement QJniObject::LocalFrame conversion.
813#include <QtCore/qjniarray.h>
815
816template <typename ...Args>
817template <typename T>
818auto QJniObject::LocalFrame<Args...>::convertToJni(T &&value)
819{
821 if constexpr (std::is_same_v<Type, QString>) {
822 return newLocalRef<jstring>(QJniObject::fromString(value));
823 } else if constexpr (QtJniTypes::IsJniArray<Type>::value) {
824 return value.arrayObject();
825 } else if constexpr (QJniArrayBase::canConvert<T>) {
826 using QJniArrayType = decltype(QJniArrayBase::fromContainer(std::forward<T>(value)));
827 using ArrayType = decltype(std::declval<QJniArrayType>().arrayObject());
828 return newLocalRef<ArrayType>(QJniArrayBase::fromContainer(std::forward<T>(value)).template object<jobject>());
829 } else if constexpr (std::is_base_of_v<QJniObject, Type>
830 || std::is_base_of_v<QtJniTypes::JObjectBase, Type>) {
831 return value.object();
832 } else {
833 return std::forward<T>(value);
834 }
835}
836
837template <typename ...Args>
838template <typename T>
839auto QJniObject::LocalFrame<Args...>::convertFromJni(QJniObject &&object)
840{
842 if constexpr (std::is_same_v<Type, QString>) {
843 return object.toString();
844 } else if constexpr (QtJniTypes::IsJniArray<Type>::value) {
845 return T(std::move(object));
846 } else if constexpr (QJniArrayBase::canConvert<Type>) {
847 // if we were to create a QJniArray from Type...
848 using QJniArrayType = decltype(QJniArrayBase::fromContainer(std::declval<Type>()));
849 // then that QJniArray would have elements of type
850 using ElementType = typename QJniArrayType::Type;
851 // construct a QJniArray from a jobject pointer of that type
852 return QJniArray<ElementType>(object.template object<jarray>()).toContainer();
853 } else if constexpr (std::is_array_v<Type>) {
854 using ElementType = std::remove_extent_t<Type>;
855 return QJniArray<ElementType>(std::move(object));
856 } else if constexpr (std::is_base_of_v<QJniObject, Type>
857 && !std::is_same_v<QJniObject, Type>) {
858 return T{std::move(object)};
859 } else if constexpr (std::is_base_of_v<QtJniTypes::JObjectBase, Type>) {
860 return T{std::move(object)};
861 } else {
862 return std::move(object);
863 }
864}
865
866
868
869#endif
870
871#endif // QJNIOBJECT_H
static JNINativeMethod methods[]
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QMetaType signature()
Combined button and popup list for selecting options.
void construct(const QtPrivate::QMetaTypeInterface *iface, void *where, const void *copy)
std::array< typename ArrayTypeHelper< ManualType, Types... >::type, sizeof...(Types)> ArrayType
Initialization
std::remove_cv_t< std::remove_reference_t< T > > remove_cvref_t
#define Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(...)
#define Q_IMPLICIT
constexpr bool operator!=(const timespec &t1, const timespec &t2)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
static QString methodName(const QDBusIntrospection::Method &method)
bool comparesEqual(const QDir &lhs, const QDir &rhs)
Definition qdir.cpp:1819
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLuint object
[3]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
GLhandleARB obj
[2]
GLuint res
static bool fromString(const QMetaObject *mo, QString s, Allocate &&allocate)
bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
Definition qrandom.cpp:1220
SSL_CTX int void * arg
#define QT_TECH_PREVIEW_API
const char className[16]
[1]
Definition qwizard.cpp:100
QSharedPointer< T > other(t)
[5]
QFrame frame
[0]
char * toString(const MyType &t)
[31]
QJSValueList args
Definition moc.h:23