Commit fc7fbbd9 authored by Volker Krause's avatar Volker Krause
Browse files

Don't make JNI_OBJECTs implicitly constructable from JNI handles

This is the equivalent of reinterpret_cast-ing from a void*, so this should
be avoided and used only when absolutely necessary. Add a helper method
for doing this.

This also makes single argument ctors with wrapper type arguments work as
intended, those were made ambigious by the ctor added via JNI_OBJECT.
parent 5930baae
......@@ -133,7 +133,7 @@ private Q_SLOTS:
QCOMPARE(obj.jniHandle().protocol()[26], QLatin1String("callMethod: overloaded (JLjava/lang/String;[S)I (Joo)"));
// ctor call
obj = TestClass(Jni::Object<android::content::Intent>(intent)); // FIXME: this require removal of the ctor in JNI_OBJECT to work without the explicit cast
obj = TestClass(intent);
QCOMPARE(obj.jniHandle().protocol().size(), 1);
QCOMPARE(obj.jniHandle().protocol()[0], QLatin1String("ctor: android/content/Intent (Landroid/content/Intent;)V"));
#if 0
......
......@@ -110,7 +110,7 @@ static void importFromIntent(JNIEnv *env, jobject that, jobject data)
{
Q_UNUSED(that)
Q_UNUSED(env)
ApplicationController::instance()->importFromIntent(KAndroidExtras::Intent(data));
ApplicationController::instance()->importFromIntent(KAndroidExtras::Jni::fromHandle<KAndroidExtras::Intent>(data));
}
static const JNINativeMethod methods[] = {
......
......@@ -22,7 +22,7 @@ Intent Activity::getIntent()
return {};
const auto intent = activity.callObjectMethod("getIntent", Jni::signature<android::content::Intent()>());
return Intent(intent);
return Intent(Jni::fromHandle<Intent>(intent));
}
bool Activity::startActivity(const Intent &intent, int receiverRequestCode)
......
......@@ -15,11 +15,6 @@
using namespace KAndroidExtras;
Intent::Intent()
{
setJniHandle(QAndroidJniObject(Jni::typeName<android::content::Intent>()));
}
Intent::~Intent() = default;
Intent::operator QAndroidJniObject() const
......
......@@ -30,7 +30,7 @@ class KANDROIDEXTRAS_EXPORT Intent
JNI_OBJECT(Intent, android::content::Intent)
public:
/** Creates a new empty intent. */
Intent();
JNI_CONSTRUCTOR(Intent)
~Intent();
/** Add a category to the intent. */
......
......@@ -13,6 +13,8 @@ namespace KAndroidExtras {
namespace java { namespace lang { struct String; } }
namespace Internal { struct FromHandleTag{}; }
namespace Jni {
template <typename T>
......@@ -21,6 +23,23 @@ inline QAndroidJniObject handle(const T &wrapper)
return wrapper.jniHandle();
}
/** Convert an untyped JNI object handle to a typed wrapper.
* This is essentially the JNI equivalent to a reinterpret_cast from a void*.
* Only use this if you are sure @p handle has the correct type, otherwise
* things will horribly go wrong.
*/
template <typename T>
inline T fromHandle(const QAndroidJniObject &handle)
{
return T(handle, Internal::FromHandleTag());
}
template <typename T>
inline T fromHandle(jobject handle)
{
return fromHandle<T>(QAndroidJniObject(handle));
}
/** Wrapper for JNI objects with a convertible C++ type.
* This provides implicit on-demand conversion to the C++ type, for types
* that don't have a manually defined wrapper.
......@@ -111,8 +130,9 @@ private: \
inline QAndroidJniObject jniHandle() const { return _m_jni_handle; } \
inline void setJniHandle(const QAndroidJniObject &h) { _m_jni_handle = h; } \
friend QAndroidJniObject KAndroidExtras::Jni::handle<Class>(const Class&); \
public: \
explicit Class(const QAndroidJniObject &h) : _m_jni_handle(h) {}
friend Class KAndroidExtras::Jni::fromHandle<Class>(const QAndroidJniObject&); \
explicit inline Class(const QAndroidJniObject &handle, KAndroidExtras::Internal::FromHandleTag) : _m_jni_handle(handle) {}
}
}
......
......@@ -41,7 +41,7 @@ namespace Internal {
public:
static inline auto toReturnValue(const QAndroidJniObject &value)
{
return RetT(value);
return Jni::fromHandle<RetT>(value);
}
};
template <typename RetT>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment