summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/kernel/qjnitypes/tst_qjnitypes.cpp
Commit message (Collapse)AuthorAgeFilesLines
* JNI: Fix error with overload resolution when passing string typesVolker Hilsheimer2024-03-061-0/+52
| | | | | | | | | | | | | | | | | | | | The variadic templates are supposed to be removed from the overload set when any of the parameters is a literal string type, as otherwise we get conflicts with the legacy overload taking class names and signatures as const char *. The detection of a literal string types was missing a few specializations, so that we ended up with the wrong overload being called, and class names getting interpreted as method names instead. Add the missing specializations, and add more test coverage for using the old overloads. Task-number: QTBUG-122235 Pick-to: 6.7 Change-Id: I5488f2009c8f62d74fac6754844f57cf64011414 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io> Reviewed-by: Rami Potinkara <rami.potinkara@qt.io> Reviewed-by: Lauri Pohjanheimo <lauri.pohjanheimo@qt.io>
* Change license for tests filesLucie Gérard2024-02-041-1/+1
| | | | | | | | | | | | According to QUIP-18 [1], all tests file should be LicenseRef-Qt-Commercial OR GPL-3.0-only [1]: https://contribute.qt-project.org/quips/18 Pick-to: 6.7 Task-number: QTBUG-121787 Change-Id: I9657df5d660820e56c96d511ea49d321c54682e8 Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de>
* JNI: allow QString as a parameter to native methodsVolker Hilsheimer2023-11-071-0/+9
| | | | | | | | | | | | | | Expect a jstring on the va_list, and implicitly construct a QString from that. As a drive-by, allow native methods to take parameters by reference, and move implementation details into a Detail namespace. Add test coverage. Change-Id: I31214938ccaea3f4d539b432e29d12434dd98377 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io> Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
* JNI: don't implement a signature for 'long' C++ typeVolker Hilsheimer2023-11-011-2/+2
| | | | | | | | | | | | On Android, `long` has the width of the system, while `jlong` is always 64 bit. If we support `long` as a signature type equivalent to `jlong`, then it becomes possible to write code that fails to compile, or in the worst case crashes at runtime, on a 32bit system. Instead, support quint64, which is always the same size as jlong. Change-Id: I60432ec7411e697b5f6e1f153216ceee0af7e0f1 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
* JNI: add QJniArray class for easier working with arraysVolker Hilsheimer2023-10-161-2/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Implements an iterator API and other standard member access functions for sequential containers so that we can use ranged-for over an object that is a jarray. Provides read-only access to individual elements (which is mostly relevant for arrays of objects), or the entire data() as a contiguous memory block (which is useful for arrays of primitive types). QJniObject call functions can return QJniArray<T> when the return type is either explicitly QJniArray<T> or T[], or their Qt equivalent (e.g. a jbyteArray can be taken or returned as a QByteArray). If the return type is a jarray type, then a QJniObject is returned as before. Arrays can be created from a Qt container through a constructor or the generic fromData named constructor in the QJniArrayBase class, which implements the generic logic. Not documented as public API yet. Added a compile-time test to verify that types are mapped correctly. The function test coverage is added to the QJniObject auto-test, as that already provides the Java test class with functions taking and returning arrays of different types. Change-Id: I0750fc4f4cce7314df3b10e122eafbcfd68297b6 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
* JNI: Fix native functions that take a declared QtJniTypes classVolker Hilsheimer2023-09-271-4/+27
| | | | | | | | | | | | | | | | | | | Now that QtJniTypes::Objects are no longer primitive types that are the same as a jobject, using those types in registered native functions breaks. JNI will call those function with a jobject on the function pointer, and lacking any type safety, the call to the registered function will proceed with a wrong type of object on the stack. To fix that, register the native function via a proxy that is a variadic argument function, and unpack the variadic arguments into a list of typed arguments, using the types we know the user-code function wants. Then call the function with a tuple of those types using std::apply, which gives us type safety and implicit conversion for free. Add a test that exercises this. Change-Id: I9f980e55d3d13f8fc16c410dc0d17dbdc200cb47 Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
* JNI: Make declared QtJniTypes classes proper QJniObjectsVolker Hilsheimer2023-09-271-0/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Instead of having a type that doesn't behave like a QJniObject, which includes not holding a proper reference on the Java object, make the QtJniTypes::Object type a QJniObject subclass that can be specialized via CRTP to provide type-specific constructor and static functions. QJniObject doesn't have a virtual destructor, but we subclass it only to add a typed interface, without adding any additional data members. Add versions of the static functions from QJniObjects to the QtJniTypes::Object so that they can be called without explicitly specifying the type or class name. This includes a constructor and named constructors. Constructing such objects means constructing a Java object of the class the object type represents, as per the Q_DECLARE_JNI_CLASS declaration. This is not without ambiguity, as constructing a type with a jobject parameter can mean that a type wrapping an existing jobject should be created, or that a Java object should be created with the provided jobject as the parameter to the constructor (e.g. a copy constructor). This ambiguity is for now inevitable; we need to be able to implicitly convert jobject to such types. However, named constructors are provided so that client code can avoid the ambiguity. To prevent unnecessary default constructed QJniObjects that are then replaced immediately with a properly constructed object, add a protected QJniObject constructor that creates an uninitialized object (e.g. with the d-pointer being nullptr), which we can then assign the constructed jobject to using the available assignment operator. Add the special copy and move constructor and assignment operators as explicit members for clarity, even though the can all be defaulted. Such QJniObject subclasses can then be transparently passed as arguments into JNI call functions that expect a jobject representation, with the QtJniTypes::Traits specialization from the type declaration providing the correct signature. QJniObject's API includes a lot of legacy overloads: with variadic arguments, a explicit signature string, and jclass/jmethodID parameters that are completely unused within Qt itself. In addition the explicit "Object" member functions to explicitly call the version that returns a jobject (and then a QJniObject). All this call-side complexity is taken care of by the compile-time signature generation, implicit class type, and template argument deduction. Overloads taking a jclass or jmethod are not used anywhere in Qt, which is perhaps an indicator that they, while nice to have, are too hard to use even for ourselves. For the modern QtJniTypes class instantiations, remove all the overhead and reduce the API to the small set of functions that are used all over the place, and that don't require an explicit signature, or class/method lookup. This is a source incompatible change, as now QJniTypes::Object is no longer a primitive type, and no longer binary equivalent to jobject. However, this is acceptable as the API has so far been undocumented, and is only used internally in Qt (and changes to adapt are largely already merged). Change-Id: I6d14c09c8165652095f30511f04dc17217245bf5 Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
* JNI: remove compatibility alias for CTStringVolker Hilsheimer2023-09-261-0/+6
| | | | | | | | | | Add compile-time testing to make sure that we can declare a JNI class String that maps to java/lang/String. Change-Id: I2b68b2b46112e56b279f3fcddc3d71847a005924 Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io> Reviewed-by: Zoltan Gera <zoltan.gera@qt.io> Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
* JNI: treat enums as their underlying typesVolker Hilsheimer2023-09-231-0/+17
| | | | | | | | | | | | | | | | | | | | Android APIs use integer constants like enum values, so they are mapped to one of the integeral types (jint, jshort, jlong etc) on the C++ side. Enable C++ code to declare an equivalent enum (scoped or unscoped), and to use that enum as a type in JNI calls by treating it as the underlying type in the signature() generator. Add a helper type trait that maps enums to their underlying type and other integral types to themselves (we can't use std::underlying_type_t on a non-enum type). Add tests. Note: Java Enums are special classes with fields; this change does not add any special support for those. Change-Id: Iec430a1553152dcf7a24209aaebbeceb1c6e38a8 Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io> Reviewed-by: Zoltan Gera <zoltan.gera@qt.io> Reviewed-by: Juha Vuolle <juha.vuolle@qt.io>
* JNI: move signature/className template functions into a template classVolker Hilsheimer2023-09-221-15/+25
| | | | | | | | | | | | | | | | | Template functions don't permit partial specialization, e.g. we cannot specialize typeSignature() to return an array signature for any std::vector or QList type. We need to do that for better array support, so move those functions as static members into a template class, which then can be specialized. Since submodules are both calling and specializing typeSignature and className as template functions, keep and use those until the porting is complete. Change-Id: I74ec957fc41f78046cd9d0f803d8cc9d1e56672b Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io> Reviewed-by: Zoltan Gera <zoltan.gera@qt.io> Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
* JNI: rename our compile-time String type to CTStringVolker Hilsheimer2023-09-221-20/+18
| | | | | | | | | | | | | | | | | | | | The type lives in the QtJniTypes namespace, which is where types end up that are declared through the Q_DECLARE_JNI_CLASS/TYPE macros. Having a String type in that namespace prevents us from declaring the Java String class as a QtJniTypes type, which is silly. Perhaps this type becomes obsolete at some point with std::string being a constexpr type in C++23, but until then we need it. It has no ABI, so renaming it us safe. Until submodules are ported, leave a compatibility alias String type, which also prevents us from declaring a String JNI class in tests until the alias is removed in a later commit. Change-Id: I489a40a9b9e94e6495cf54548238438e9220d5c1 Reviewed-by: Zoltan Gera <zoltan.gera@qt.io> Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io> Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io>
* JNI: replace TYPE declarations with CLASS declarationsVolker Hilsheimer2023-09-201-1/+1
| | | | | | | | | | | | | That we have two macros to declare a C++ type to represent a Java class is confusing. The TYPE macro as of now allows us to declare array types, but with QJniArray we won't need that anymore, and can just use Class[] as the type instead. Changing that will be a follow-up commit; for now, get rid of TYPE-usages to declare regular classes. Change-Id: Iea0a9548772ca701148442412cf6ad567583213f Reviewed-by: Zoltan Gera <zoltan.gera@qt.io> Reviewed-by: Petri Virkkunen <petri.virkkunen@qt.io> Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
* JNI: add generic support for array-typesVolker Hilsheimer2022-10-101-0/+9
| | | | | | | | | | | | | | | | | | | The typeSignature for a type T[] is always "[" + typeSignature<t>, so we can just implicitly support arrays of any known type. To prevent support for multi-dimensional arrays, make sure that the underlying type is not also an array. By adding a QJniTypes::isArrayType in addition (that is true for any type with a signature starting with '['), methods like QJniObject::callMethod could then return a special QJniArray type that provides array-specific functionality. As a drive-by, and since all lines need to be touched to add braces, replace std::is_same<>::value with std::is_same_v. Change-Id: Iccadf03cfceb8544381a8f635bb54baeddf46c99 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
* Add compile-time generation of JNI class namesVolker Hilsheimer2022-05-271-0/+22
| | | | | | | | | | | | | | | | | | | | | As with method signatures, register class names using template function specialization in the QtJniTypes namespace, and then declare C++ types as JNI classes with a class name string. Such classes implicitly get registered as JNI types as well. Add a QJniObject construct method (since C++ constructors that are templates cannot be explicitly instantiated with a type), and a QJniEnvironment::findClass overload. Add test coverage, also for the recently added macros for native methods. As a drive-by, change the name of the Q_JNI_DECLARE_NATIVE_METHOD macro to Q_DECLARE_JNI_NATIVE_METHOD for consistency. Change-Id: Ic19562d78da726f202b3bdf4e9354e8ad24d8bd9 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
* Return specific types for frequently used Java objectsVolker Hilsheimer2022-05-171-0/+9
| | | | | | | | | | | | | | | | | | This allows us to specialize JNI type signature templates for e.g. the context object, which in Java signatures is "android/content/Context". Introduce a Q_DECLARE_JNI_TYPE macro that takes care of the plumbing. The types declared this way live in the QtJniTypes namespace, and transparently convert from and to jobject. Since jobject is a typedef to _jobject* we cannot create a subclass. Use a "Object" superclass that we can provide a QJniObject constructor for so that we don't require the QJniObject declaration to be able to use the macro. The APIs in the QNativeInterface namespace doesn't provide source or binary compatibility guarantees, so we can change the return types. Change-Id: I4cf9fa734ec9a5550b6fddeb14ef0ffd72663f29 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
* Use SPDX license identifiersLucie Gérard2022-05-161-27/+2
| | | | | | | | | | | | | Replace the current license disclaimer in files by a SPDX-License-Identifier. Files that have to be modified by hand are modified. License files are organized under LICENSES directory. Task-number: QTBUG-67283 Change-Id: Id880c92784c40f3bbde861c0d93f58151c18b9f1 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
* Generate JNI signature strings at compile timeVolker Hilsheimer2022-05-051-0/+118
Introduce an internal QtJniTypes namespace with types that allow us to concatenate string literals at compile time. This makes it possible to generate arbitrary strings based on types, which we can then use as signatures to JNI method calls. Move some of the private members of QJniObject into the QtJniTypes namespace for consistency, and to allow further template specialization by user code to make other types and their JNI signature string known. Remove the "Jni" prefix from names. Use the compile-time generated string in QJniObject methods that created the signature string at runtime, which involved a temporary memory allocation. Treat 'void' as a primitive type (with signature string 'V'), and remove redundant template specializations. Add a test case to verify the the strings are constructed correctly at compile time. Change-Id: I5e3895a97f7dc1b86961f7a7855b899d9203037d Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io> Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>