#pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunknown-pragmas" #pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection" #pragma once #include #include #include #include #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName &) = delete; \ void operator=(const TypeName &) = delete namespace lsplant { template class> struct is_instance : public std::false_type {}; template class U> struct is_instance, U> : public std::true_type {}; template class U> inline constexpr bool is_instance_v = is_instance::value; template concept JObject = std::is_base_of_v, std::remove_pointer_t>; template class ScopedLocalRef { public: using BaseType [[maybe_unused]] = T; ScopedLocalRef(JNIEnv *env, T localRef) : env_(env), local_ref_(localRef) {} ScopedLocalRef(ScopedLocalRef &&s) noexcept : env_(s.env_), local_ref_(s.release()) {} template ScopedLocalRef(ScopedLocalRef &&s) noexcept : env_(s.env_), local_ref_((T)s.release()) {} explicit ScopedLocalRef(JNIEnv *env) noexcept : env_(env), local_ref_(nullptr) {} ~ScopedLocalRef() { reset(); } void reset(T ptr = nullptr) { if (ptr != local_ref_) { if (local_ref_ != nullptr) { env_->DeleteLocalRef(local_ref_); } local_ref_ = ptr; } } [[nodiscard]] T release() { T localRef = local_ref_; local_ref_ = nullptr; return localRef; } T get() const { return local_ref_; } operator T() const { return local_ref_; } // We do not expose an empty constructor as it can easily lead to errors // using common idioms, e.g.: // ScopedLocalRef<...> ref; // ref.reset(...); // Move assignment operator. ScopedLocalRef &operator=(ScopedLocalRef &&s) noexcept { reset(s.release()); env_ = s.env_; return *this; } operator bool() const { return local_ref_; } template friend class ScopedLocalRef; friend class JUTFString; private: JNIEnv *env_; T local_ref_; DISALLOW_COPY_AND_ASSIGN(ScopedLocalRef); }; class JNIScopeFrame { JNIEnv *env_; public: JNIScopeFrame(JNIEnv *env, jint size) : env_(env) { env_->PushLocalFrame(size); } ~JNIScopeFrame() { env_->PopLocalFrame(nullptr); } }; template concept ScopeOrRaw = std::is_convertible_v || (is_instance_v, ScopedLocalRef> &&std::is_convertible_v::BaseType, U>); template concept ScopeOrClass = ScopeOrRaw; template concept ScopeOrObject = ScopeOrRaw; inline ScopedLocalRef ClearException(JNIEnv *env) { if (auto exception = env->ExceptionOccurred()) { env->ExceptionClear(); static jclass log = (jclass)env->NewGlobalRef(env->FindClass("android/util/Log")); static jmethodID toString = env->GetStaticMethodID( log, "getStackTraceString", "(Ljava/lang/Throwable;)Ljava/lang/String;"); auto str = (jstring)env->CallStaticObjectMethod(log, toString, exception); env->DeleteLocalRef(exception); return {env, str}; } return {env, nullptr}; } template [[maybe_unused]] inline auto UnwrapScope(T &&x) { if constexpr (std::is_same_v, std::string_view>) return x.data(); else if constexpr (is_instance_v, ScopedLocalRef>) return x.get(); else return std::forward(x); } template [[maybe_unused]] inline auto WrapScope(JNIEnv *env, T &&x) { if constexpr (std::is_convertible_v) { return ScopedLocalRef(env, std::forward(x)); } else return x; } template [[maybe_unused]] inline auto WrapScope(JNIEnv *env, std::tuple &&x, std::index_sequence) { return std::make_tuple(WrapScope(env, std::forward(std::get(x)))...); } template [[maybe_unused]] inline auto WrapScope(JNIEnv *env, std::tuple &&x) { return WrapScope(env, std::forward>(x), std::make_index_sequence()); } inline auto JNI_NewStringUTF(JNIEnv *env, std::string_view sv) { return ScopedLocalRef(env, env->NewStringUTF(sv.data())); } class JUTFString { public: inline JUTFString(JNIEnv *env, jstring jstr) : JUTFString(env, jstr, nullptr) {} inline JUTFString(const ScopedLocalRef &jstr) : JUTFString(jstr.env_, jstr.local_ref_, nullptr) {} inline JUTFString(JNIEnv *env, jstring jstr, const char *default_cstr) : env_(env), jstr_(jstr) { if (env_ && jstr_) cstr_ = env_->GetStringUTFChars(jstr, nullptr); else cstr_ = default_cstr; } inline operator const char *() const { return cstr_; } inline operator const std::string() const { return cstr_; } inline operator const bool() const { return cstr_ != nullptr; } inline auto get() const { return cstr_; } inline ~JUTFString() { if (env_ && jstr_) env_->ReleaseStringUTFChars(jstr_, cstr_); } JUTFString(JUTFString &&other) : env_(std::move(other.env_)), jstr_(std::move(other.jstr_)), cstr_(std::move(other.cstr_)) { other.cstr_ = nullptr; } JUTFString &operator=(JUTFString &&other) { if (&other != this) { env_ = std::move(other.env_); jstr_ = std::move(other.jstr_); cstr_ = std::move(other.cstr_); other.cstr_ = nullptr; } return *this; } private: JNIEnv *env_; jstring jstr_; const char *cstr_; JUTFString(const JUTFString &) = delete; JUTFString &operator=(const JUTFString &) = delete; }; template requires(std::is_function_v) [[maybe_unused]] inline auto JNI_SafeInvoke(JNIEnv *env, Func JNIEnv::*f, Args &&...args) { struct finally { finally(JNIEnv *env) : env_(env) {} ~finally() { if (auto exception = ClearException(env_)) { __android_log_print(ANDROID_LOG_ERROR, #ifdef LOG_TAG LOG_TAG, #else "JNIHelper", #endif "%s", JUTFString(env_, exception.get()).get()); } } JNIEnv *env_; } _(env); if constexpr (!std::is_same_v(args)))...>>) return WrapScope(env, (env->*f)(UnwrapScope(std::forward(args))...)); else (env->*f)(UnwrapScope(std::forward(args))...); } // functions to class [[maybe_unused]] inline auto JNI_FindClass(JNIEnv *env, std::string_view name) { return JNI_SafeInvoke(env, &JNIEnv::FindClass, name); } template [[maybe_unused]] inline auto JNI_GetObjectClass(JNIEnv *env, const Object &obj) { return JNI_SafeInvoke(env, &JNIEnv::GetObjectClass, obj); } // functions to field template [[maybe_unused]] inline auto JNI_GetFieldID(JNIEnv *env, Class &&clazz, std::string_view name, std::string_view sig) { return JNI_SafeInvoke(env, &JNIEnv::GetFieldID, std::forward(clazz), name, sig); } // getters template [[maybe_unused]] inline auto JNI_GetObjectField(JNIEnv *env, Object &&obj, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetObjectField, std::forward(obj), fieldId); } template [[maybe_unused]] inline auto JNI_GetBooleanField(JNIEnv *env, Object &&obj, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetBooleanField, std::forward(obj), fieldId); } template [[maybe_unused]] inline auto JNI_GetByteField(JNIEnv *env, Object &&obj, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetByteField, std::forward(obj), fieldId); } template [[maybe_unused]] inline auto JNI_GetCharField(JNIEnv *env, Object &&obj, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetCharField, std::forward(obj), fieldId); } template [[maybe_unused]] inline auto JNI_GetShortField(JNIEnv *env, Object &&obj, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetShortField, std::forward(obj), fieldId); } template [[maybe_unused]] inline auto JNI_GetIntField(JNIEnv *env, Object &&obj, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetIntField, std::forward(obj), fieldId); } template [[maybe_unused]] inline auto JNI_GetLongField(JNIEnv *env, Object &&obj, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetLongField, std::forward(obj), fieldId); } template [[maybe_unused]] inline auto JNI_GetFloatField(JNIEnv *env, Object &&obj, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetFloatField, std::forward(obj), fieldId); } template [[maybe_unused]] inline auto JNI_GetDoubleField(JNIEnv *env, Object &&obj, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetDoubleField, std::forward(obj), fieldId); } // setters template [[maybe_unused]] inline auto JNI_SetObjectField(JNIEnv *env, Object &&obj, jfieldID fieldId, const Object &value) { return JNI_SafeInvoke(env, &JNIEnv::SetObjectField, std::forward(obj), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetBooleanField(JNIEnv *env, Object &&obj, jfieldID fieldId, jboolean value) { return JNI_SafeInvoke(env, &JNIEnv::SetBooleanField, std::forward(obj), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetByteField(JNIEnv *env, Object &&obj, jfieldID fieldId, jbyte value) { return JNI_SafeInvoke(env, &JNIEnv::SetByteField, std::forward(obj), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetCharField(JNIEnv *env, Object &&obj, jfieldID fieldId, jchar value) { return JNI_SafeInvoke(env, &JNIEnv::SetCharField, std::forward(obj), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetShortField(JNIEnv *env, Object &&obj, jfieldID fieldId, jshort value) { return JNI_SafeInvoke(env, &JNIEnv::SetShortField, std::forward(obj), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetIntField(JNIEnv *env, Object &&obj, jfieldID fieldId, jint value) { return JNI_SafeInvoke(env, &JNIEnv::SetIntField, std::forward(obj), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetLongField(JNIEnv *env, Object &&obj, jfieldID fieldId, jlong value) { return JNI_SafeInvoke(env, &JNIEnv::SetLongField, std::forward(obj), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetFloatField(JNIEnv *env, Object &&obj, jfieldID fieldId, jfloat value) { return JNI_SafeInvoke(env, &JNIEnv::SetFloatField, std::forward(obj), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetDoubleField(JNIEnv *env, Object &&obj, jfieldID fieldId, jdouble value) { return JNI_SafeInvoke(env, &JNIEnv::SetDoubleField, std::forward(obj), fieldId, value); } // functions to static field template [[maybe_unused]] inline auto JNI_GetStaticFieldID(JNIEnv *env, Class &&clazz, std::string_view name, std::string_view sig) { return JNI_SafeInvoke(env, &JNIEnv::GetStaticFieldID, std::forward(clazz), name, sig); } // getters template [[maybe_unused]] inline auto JNI_GetStaticObjectField(JNIEnv *env, Class &&clazz, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetStaticObjectField, std::forward(clazz), fieldId); } template [[maybe_unused]] inline auto JNI_GetStaticBooleanField(JNIEnv *env, Class &&clazz, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetStaticBooleanField, std::forward(clazz), fieldId); } template [[maybe_unused]] inline auto JNI_GetStaticByteField(JNIEnv *env, Class &&clazz, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetStaticByteField, std::forward(clazz), fieldId); } template [[maybe_unused]] inline auto JNI_GetStaticCharField(JNIEnv *env, Class &&clazz, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetStaticCharField, std::forward(clazz), fieldId); } template [[maybe_unused]] inline auto JNI_GetStaticShortField(JNIEnv *env, Class &&clazz, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetStaticShortField, std::forward(clazz), fieldId); } template [[maybe_unused]] inline auto JNI_GetStaticIntField(JNIEnv *env, Class &&clazz, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetStaticIntField, std::forward(clazz), fieldId); } template [[maybe_unused]] inline auto JNI_GetStaticLongField(JNIEnv *env, Class &&clazz, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetStaticLongField, std::forward(clazz), fieldId); } template [[maybe_unused]] inline auto JNI_GetStaticFloatField(JNIEnv *env, Class &&clazz, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetStaticFloatField, std::forward(clazz), fieldId); } template [[maybe_unused]] inline auto JNI_GetStaticDoubleField(JNIEnv *env, Class &&clazz, jfieldID fieldId) { return JNI_SafeInvoke(env, &JNIEnv::GetStaticDoubleField, std::forward(clazz), fieldId); } // setters template [[maybe_unused]] inline auto JNI_SetStaticObjectField(JNIEnv *env, Class &&clazz, jfieldID fieldId, const Object &value) { return JNI_SafeInvoke(env, &JNIEnv::SetStaticObjectField, std::forward(clazz), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetStaticBooleanField(JNIEnv *env, Class &&clazz, jfieldID fieldId, jboolean value) { return JNI_SafeInvoke(env, &JNIEnv::SetStaticBooleanField, std::forward(clazz), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetStaticByteField(JNIEnv *env, Class &&clazz, jfieldID fieldId, jbyte value) { return JNI_SafeInvoke(env, &JNIEnv::SetStaticByteField, std::forward(clazz), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetStaticCharField(JNIEnv *env, Class &&clazz, jfieldID fieldId, jchar value) { return JNI_SafeInvoke(env, &JNIEnv::SetStaticCharField, std::forward(clazz), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetStaticShortField(JNIEnv *env, Class &&clazz, jfieldID fieldId, jshort value) { return JNI_SafeInvoke(env, &JNIEnv::SetStaticShortField, std::forward(clazz), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetStaticIntField(JNIEnv *env, Class &&clazz, jfieldID fieldId, jint value) { return JNI_SafeInvoke(env, &JNIEnv::SetStaticIntField, std::forward(clazz), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetStaticLongField(JNIEnv *env, Class &&clazz, jfieldID fieldId, jlong value) { return JNI_SafeInvoke(env, &JNIEnv::SetStaticLongField, std::forward(clazz), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetStaticFloatField(JNIEnv *env, Class &&clazz, jfieldID fieldId, jfloat value) { return JNI_SafeInvoke(env, &JNIEnv::SetStaticFloatField, std::forward(clazz), fieldId, value); } template [[maybe_unused]] inline auto JNI_SetStaticDoubleField(JNIEnv *env, Class &&clazz, jfieldID fieldId, jdouble value) { return JNI_SafeInvoke(env, &JNIEnv::SetStaticDoubleField, std::forward(clazz), fieldId, value); } template [[maybe_unused]] inline auto JNI_ToReflectedMethod(JNIEnv *env, Class &&clazz, jmethodID method, jboolean isStatic = JNI_FALSE) { return JNI_SafeInvoke(env, &JNIEnv::ToReflectedMethod, std::forward(clazz), method, isStatic); } // functions to method // virtual methods template [[maybe_unused]] inline auto JNI_GetMethodID(JNIEnv *env, Class &&clazz, std::string_view name, std::string_view sig) { return JNI_SafeInvoke(env, &JNIEnv::GetMethodID, std::forward(clazz), name, sig); } template [[maybe_unused]] inline auto JNI_CallVoidMethod(JNIEnv *env, Object &&obj, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallVoidMethod, std::forward(obj), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallObjectMethod(JNIEnv *env, Object &&obj, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallObjectMethod, std::forward(obj), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallBooleanMethod(JNIEnv *env, Object &&obj, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallBooleanMethod, std::forward(obj), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallByteMethod(JNIEnv *env, Object &&obj, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallByteMethod, std::forward(obj), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallCharMethod(JNIEnv *env, Object &&obj, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallCharMethod, std::forward(obj), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallShortMethod(JNIEnv *env, Object &&obj, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallShortMethod, std::forward(obj), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallIntMethod(JNIEnv *env, Object &&obj, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallIntMethod, std::forward(obj), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallLongMethod(JNIEnv *env, Object &&obj, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallLongMethod, std::forward(obj), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallFloatMethod(JNIEnv *env, Object &&obj, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallFloatMethod, std::forward(obj), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallDoubleMethod(JNIEnv *env, Object &&obj, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallDoubleMethod, std::forward(obj), method, std::forward(args)...); } // static methods template [[maybe_unused]] inline auto JNI_GetStaticMethodID(JNIEnv *env, Class &&clazz, std::string_view name, std::string_view sig) { return JNI_SafeInvoke(env, &JNIEnv::GetStaticMethodID, std::forward(clazz), name, sig); } template [[maybe_unused]] inline auto JNI_CallStaticVoidMethod(JNIEnv *env, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallStaticVoidMethod, std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallStaticObjectMethod(JNIEnv *env, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallStaticObjectMethod, std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallStaticBooleanMethod(JNIEnv *env, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallStaticBooleanMethod, std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallStaticByteMethod(JNIEnv *env, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallStaticByteMethod, std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallStaticCharMethod(JNIEnv *env, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallStaticCharMethod, std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallStaticShortMethod(JNIEnv *env, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallStaticShortMethod, std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallStaticIntMethod(JNIEnv *env, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallStaticIntMethod, std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallStaticLongMethod(JNIEnv *env, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallStaticLongMethod, std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallStaticFloatMethod(JNIEnv *env, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallStaticFloatMethod, std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallStaticDoubleMethod(JNIEnv *env, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallStaticDoubleMethod, std::forward(clazz), method, std::forward(args)...); } // non-vritual methods template [[maybe_unused]] inline auto JNI_CallCallNonvirtualVoidMethod(JNIEnv *env, Object &&obj, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallNonvirtualVoidMethod, std::forward(obj), std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallCallNonvirtualObjectMethod(JNIEnv *env, Object &&obj, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallNonvirtualObjectMethod, std::forward(obj), std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallCallNonvirtualBooleanMethod(JNIEnv *env, Object &&obj, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallNonvirtualBooleanMethod, std::forward(obj), std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallCallNonvirtualByteMethod(JNIEnv *env, Object &&obj, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallNonvirtualByteMethod, std::forward(obj), std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallCallNonvirtualCharMethod(JNIEnv *env, Object &&obj, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallNonvirtualCharMethod, std::forward(obj), std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallCallNonvirtualShortMethod(JNIEnv *env, Object &&obj, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallNonvirtualShortMethod, std::forward(obj), std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallCallNonvirtualIntMethod(JNIEnv *env, Object &&obj, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallNonvirtualIntMethod, std::forward(obj), std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallCallNonvirtualLongMethod(JNIEnv *env, Object &&obj, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallNonvirtualLongMethod, std::forward(obj), std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallCallNonvirtualFloatMethod(JNIEnv *env, Object &&obj, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallNonvirtualFloatMethod, std::forward(obj), std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_CallCallNonvirtualDoubleMethod(JNIEnv *env, Object &&obj, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::CallNonvirtualDoubleMethod, std::forward(obj), std::forward(clazz), method, std::forward(args)...); } // functions to array template Array> [[maybe_unused]] inline auto JNI_GetArrayLength(JNIEnv *env, const Array &array) { return JNI_SafeInvoke(env, &JNIEnv::GetArrayLength, array); } // newers template [[maybe_unused]] inline auto JNI_NewObjectArray(JNIEnv *env, jsize len, Class &&clazz, const Object &init) { return JNI_SafeInvoke(env, &JNIEnv::NewObjectArray, len, std::forward(clazz), init); } [[maybe_unused]] inline auto JNI_NewBooleanArray(JNIEnv *env, jsize len) { return JNI_SafeInvoke(env, &JNIEnv::NewBooleanArray, len); } [[maybe_unused]] inline auto JNI_NewByteArray(JNIEnv *env, jsize len) { return JNI_SafeInvoke(env, &JNIEnv::NewByteArray, len); } [[maybe_unused]] inline auto JNI_NewCharArray(JNIEnv *env, jsize len) { return JNI_SafeInvoke(env, &JNIEnv::NewCharArray, len); } [[maybe_unused]] inline auto JNI_NewShortArray(JNIEnv *env, jsize len) { return JNI_SafeInvoke(env, &JNIEnv::NewShortArray, len); } [[maybe_unused]] inline auto JNI_NewIntArray(JNIEnv *env, jsize len) { return JNI_SafeInvoke(env, &JNIEnv::NewIntArray, len); } [[maybe_unused]] inline auto JNI_NewLongArray(JNIEnv *env, jsize len) { return JNI_SafeInvoke(env, &JNIEnv::NewLongArray, len); } [[maybe_unused]] inline auto JNI_NewFloatArray(JNIEnv *env, jsize len) { return JNI_SafeInvoke(env, &JNIEnv::NewFloatArray, len); } [[maybe_unused]] inline auto JNI_NewDoubleArray(JNIEnv *env, jsize len) { return JNI_SafeInvoke(env, &JNIEnv::NewDoubleArray, len); } template Array> [[maybe_unused]] inline auto JNI_GetObjectArrayElement(JNIEnv *env, const Array &array, jsize index) { return JNI_SafeInvoke(env, &JNIEnv::GetObjectArrayElement, array, index); } template Array, ScopeOrObject Object> [[maybe_unused]] inline auto JNI_SetObjectArrayElement(JNIEnv *env, const Array &array, jsize index, Object &&obj) { return JNI_SafeInvoke(env, &JNIEnv::SetObjectArrayElement, array, index, obj); } template [[maybe_unused]] inline auto JNI_NewObject(JNIEnv *env, Class &&clazz, jmethodID method, Args &&...args) { return JNI_SafeInvoke(env, &JNIEnv::NewObject, std::forward(clazz), method, std::forward(args)...); } template [[maybe_unused]] inline auto JNI_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity) { return JNI_SafeInvoke(env, &JNIEnv::NewDirectByteBuffer, address, capacity); } template [[maybe_unused]] inline auto JNI_RegisterNatives(JNIEnv *env, Class &&clazz, const JNINativeMethod *methods, jint size) { return JNI_SafeInvoke(env, &JNIEnv::RegisterNatives, std::forward(clazz), methods, size); } template [[maybe_unused]] inline auto JNI_IsInstanceOf(JNIEnv *env, Object &&obj, Class &&clazz) { return JNI_SafeInvoke(env, &JNIEnv::IsInstanceOf, std::forward(obj), std::forward(clazz)); } template [[maybe_unused]] inline auto JNI_NewGlobalRef(JNIEnv *env, Object &&x) { return (decltype(UnwrapScope(std::forward(x))))env->NewGlobalRef( UnwrapScope(std::forward(x))); } template [[maybe_unused]] inline auto JNI_Cast(ScopedLocalRef &&x) requires( std::is_convertible_v) { return ScopedLocalRef(std::move(x)); } } // namespace lsplant #undef DISALLOW_COPY_AND_ASSIGN #pragma clang diagnostic pop