From bc4cf1cb93c90a7ed572530962bbf3b6d932722b Mon Sep 17 00:00:00 2001 From: Ryan Pavlik <ryan.pavlik@collabora.com> Date: Fri, 30 Apr 2021 17:55:34 -0500 Subject: [PATCH] external/jnipp: Move away from explicit instantiation of function templates. Makes it too hard to track down errors: they showed up as linker errors, instead of compiler errors. --- src/external/jnipp/jnipp.cpp | 46 ++++++++++++++++++------------------ src/external/jnipp/jnipp.h | 43 +++++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 27 deletions(-) diff --git a/src/external/jnipp/jnipp.cpp b/src/external/jnipp/jnipp.cpp index 2c558bda6..a250b76cd 100644 --- a/src/external/jnipp/jnipp.cpp +++ b/src/external/jnipp/jnipp.cpp @@ -353,20 +353,20 @@ namespace jni return _handle == nullptr || env()->IsSameObject(_handle, nullptr); } - template <> void Object::callMethod(method_t method, internal::value_t* args) const + void Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<void> const&) const { env()->CallVoidMethodA(_handle, method, (jvalue*) args); handleJavaExceptions(); } - template <> bool Object::callMethod(method_t method, internal::value_t* args) const + bool Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<bool> const&) const { auto result = env()->CallBooleanMethodA(_handle, method, (jvalue*) args); handleJavaExceptions(); return result != 0; } - template <> bool Object::get(field_t field) const + bool Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<bool> const&) const { return env()->GetBooleanField(_handle, field) != 0; } @@ -376,122 +376,122 @@ namespace jni env()->SetBooleanField(_handle, field, value); } - template <> byte_t Object::callMethod(method_t method, internal::value_t* args) const + byte_t Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<byte_t> const&) const { auto result = env()->CallByteMethodA(_handle, method, (jvalue*) args); handleJavaExceptions(); return result; } - template <> wchar_t Object::callMethod(method_t method, internal::value_t* args) const + wchar_t Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<wchar_t> const&) const { auto result = env()->CallCharMethodA(_handle, method, (jvalue*) args); handleJavaExceptions(); return result; } - template <> short Object::callMethod(method_t method, internal::value_t* args) const + short Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<short> const&) const { auto result = env()->CallShortMethodA(_handle, method, (jvalue*) args); handleJavaExceptions(); return result; } - template <> int Object::callMethod(method_t method, internal::value_t* args) const + int Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<int> const&) const { auto result = env()->CallIntMethodA(_handle, method, (jvalue*) args); handleJavaExceptions(); return result; } - template <> long long Object::callMethod(method_t method, internal::value_t* args) const + long long Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<long long> const&) const { auto result = env()->CallLongMethodA(_handle, method, (jvalue*) args); handleJavaExceptions(); return result; } - template <> float Object::callMethod(method_t method, internal::value_t* args) const + float Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<float> const&) const { auto result = env()->CallFloatMethodA(_handle, method, (jvalue*) args); handleJavaExceptions(); return result; } - template <> double Object::callMethod(method_t method, internal::value_t* args) const + double Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<double> const&) const { auto result = env()->CallDoubleMethodA(_handle, method, (jvalue*) args); handleJavaExceptions(); return result; } - template <> std::string Object::callMethod(method_t method, internal::value_t* args) const + std::string Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<std::string> const&) const { auto result = env()->CallObjectMethodA(_handle, method, (jvalue*) args); handleJavaExceptions(); return toString(result); } - template <> std::wstring Object::callMethod(method_t method, internal::value_t* args) const + std::wstring Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<std::wstring> const&) const { auto result = env()->CallObjectMethodA(_handle, method, (jvalue*) args); handleJavaExceptions(); return toWString(result); } - template <> jni::Object Object::callMethod(method_t method, internal::value_t* args) const + jni::Object Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<jni::Object> const&) const { auto result = env()->CallObjectMethodA(_handle, method, (jvalue*) args); handleJavaExceptions(); return Object(result, DeleteLocalInput); } - template <> byte_t Object::get(field_t field) const + byte_t Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<byte_t> const&) const { return env()->GetByteField(_handle, field); } - template <> wchar_t Object::get(field_t field) const + wchar_t Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<wchar_t> const&) const { return env()->GetCharField(_handle, field); } - template <> short Object::get(field_t field) const + short Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<short> const&) const { return env()->GetShortField(_handle, field); } - template <> int Object::get(field_t field) const + int Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<int> const&) const { return env()->GetIntField(_handle, field); } - template <> long long Object::get(field_t field) const + long long Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<long long> const&) const { return env()->GetLongField(_handle, field); } - template <> float Object::get(field_t field) const + float Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<float> const&) const { return env()->GetFloatField(_handle, field); } - template <> double Object::get(field_t field) const + double Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<double> const&) const { return env()->GetDoubleField(_handle, field); } - template <> std::string Object::get(field_t field) const + std::string Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<std::string> const&) const { return toString(env()->GetObjectField(_handle, field)); } - template <> std::wstring Object::get(field_t field) const + std::wstring Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<std::wstring> const&) const { return toWString(env()->GetObjectField(_handle, field)); } - template <> Object Object::get(field_t field) const + Object Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<Object> const&) const { return Object(env()->GetObjectField(_handle, field), DeleteLocalInput); } diff --git a/src/external/jnipp/jnipp.h b/src/external/jnipp/jnipp.h index aa20c217d..70515c979 100644 --- a/src/external/jnipp/jnipp.h +++ b/src/external/jnipp/jnipp.h @@ -176,6 +176,11 @@ namespace jni }; long getArrayLength(jarray array); + + template<typename T> + struct ReturnTypeWrapper{ + using type = T; + }; } /** @@ -282,7 +287,7 @@ namespace jni \return The method's return value. */ template <class TReturn> - TReturn call(method_t method) const { return callMethod<TReturn>(method, nullptr); } + TReturn call(method_t method) const { return callMethod(method, nullptr, internal::ReturnTypeWrapper<TReturn>{}); } /** Calls the method on this Object with the given name, and no arguments. @@ -312,7 +317,7 @@ namespace jni template <class TReturn, class... TArgs> TReturn call(method_t method, const TArgs&... args) const { internal::ArgArray<TArgs...> transform(args...); - return callMethod<TReturn>(method, transform.values); + return callMethod(method, transform.values, internal::ReturnTypeWrapper<TReturn>{}); } /** @@ -342,7 +347,11 @@ namespace jni \return The field's value. */ template <class TType> - TType get(field_t field) const; + TType get(field_t field) const { + // If you get a compile error here, then you've asked for a type + // we don't know how to get from JNI directly. + return getFieldValue(field, internal::ReturnTypeWrapper<TType>{}); + } /** Gets a field value from this Object. The field must belong to the @@ -410,7 +419,33 @@ namespace jni method_t getMethod(const char* name, const char* signature) const; method_t getMethod(const char* nameAndSignature) const; field_t getField(const char* name, const char* signature) const; - template <class TType> TType callMethod(method_t method, internal::value_t* values) const; + + void callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<void> const&) const; + bool callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<bool> const&) const; + byte_t callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<byte_t> const&) const; + wchar_t callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<wchar_t> const&) const; + short callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<short> const&) const; + int callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<int> const&) const; + long long callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<long long> const&) const; + float callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<float> const&) const; + double callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<double> const&) const; + std::string callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<std::string> const&) const; + std::wstring callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<std::wstring> const&) const; + jni::Object callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<jni::Object> const&) const; + + + void getFieldValue(field_t field, internal::ReturnTypeWrapper<void> const&) const; + bool getFieldValue(field_t field, internal::ReturnTypeWrapper<bool> const&) const; + byte_t getFieldValue(field_t field, internal::ReturnTypeWrapper<byte_t> const&) const; + wchar_t getFieldValue(field_t field, internal::ReturnTypeWrapper<wchar_t> const&) const; + short getFieldValue(field_t field, internal::ReturnTypeWrapper<short> const&) const; + int getFieldValue(field_t field, internal::ReturnTypeWrapper<int> const&) const; + long long getFieldValue(field_t field, internal::ReturnTypeWrapper<long long> const&) const; + float getFieldValue(field_t field, internal::ReturnTypeWrapper<float> const&) const; + double getFieldValue(field_t field, internal::ReturnTypeWrapper<double> const&) const; + std::string getFieldValue(field_t field, internal::ReturnTypeWrapper<std::string> const&) const; + std::wstring getFieldValue(field_t field, internal::ReturnTypeWrapper<std::wstring> const&) const; + jni::Object getFieldValue(field_t field, internal::ReturnTypeWrapper<jni::Object> const&) const; // Instance Variables jobject _handle;