You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
8.8 KiB

/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Utility class that provides similar calls like JNIEnv, but performs
// additional checks on them, so that it's harder to use them incorrectly.
#ifndef LIBTEXTCLASSIFIER_UTILS_JAVA_JNI_HELPER_H_
#define LIBTEXTCLASSIFIER_UTILS_JAVA_JNI_HELPER_H_
#include <jni.h>
#include <string>
#include "utils/base/status.h"
#include "utils/base/statusor.h"
#include "utils/java/jni-base.h"
#define TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN \
if (!EnsureLocalCapacity(env, 1)) { \
TC3_LOG(ERROR) << "EnsureLocalCapacity(1) failed."; \
return {Status::UNKNOWN}; \
}
#define TC3_NO_EXCEPTION_OR_RETURN \
if (JniExceptionCheckAndClear(env)) { \
return {Status::UNKNOWN}; \
}
#define TC3_NOT_NULL_OR_RETURN \
if (result == nullptr) { \
return {Status::UNKNOWN}; \
}
#define TC3_DEFINE_VARIADIC_SCOPED_LOCAL_REF_ENV_METHOD( \
METHOD_NAME, RETURN_TYPE, INPUT_TYPE, POST_CHECK) \
template <typename T = RETURN_TYPE> \
static StatusOr<ScopedLocalRef<T>> METHOD_NAME( \
JNIEnv* env, INPUT_TYPE object, jmethodID method_id, ...) { \
TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN; \
\
va_list args; \
va_start(args, method_id); \
ScopedLocalRef<T> result( \
reinterpret_cast<T>(env->METHOD_NAME##V(object, method_id, args)), \
env); \
POST_CHECK \
va_end(args); \
\
TC3_NO_EXCEPTION_OR_RETURN; \
return result; \
}
#define TC3_JNI_NO_CHECK \
{}
namespace libtextclassifier3 {
class JniHelper {
public:
// Misc methods.
static StatusOr<ScopedLocalRef<jclass>> FindClass(JNIEnv* env,
const char* class_name);
static StatusOr<ScopedLocalRef<jclass>> GetObjectClass(JNIEnv* env,
jobject object);
template <typename T = jobject>
static StatusOr<ScopedLocalRef<T>> GetObjectArrayElement(JNIEnv* env,
jobjectArray array,
jsize index);
static StatusOr<jmethodID> GetMethodID(JNIEnv* env, jclass clazz,
const char* method_name,
const char* signature);
static StatusOr<jmethodID> GetStaticMethodID(JNIEnv* env, jclass clazz,
const char* method_name,
const char* signature);
static StatusOr<jfieldID> GetFieldID(JNIEnv* env, jclass clazz,
const char* field_name,
const char* signature);
static StatusOr<jfieldID> GetStaticFieldID(JNIEnv* env, jclass clazz,
const char* field_name,
const char* signature);
static StatusOr<ScopedLocalRef<jobject>> GetStaticObjectField(
JNIEnv* env, jclass class_name, jfieldID field_id);
static StatusOr<jint> GetStaticIntField(JNIEnv* env, jclass class_name,
jfieldID field_id);
// New* methods.
TC3_DEFINE_VARIADIC_SCOPED_LOCAL_REF_ENV_METHOD(NewObject, jobject, jclass,
TC3_NOT_NULL_OR_RETURN);
static StatusOr<ScopedLocalRef<jobjectArray>> NewObjectArray(
JNIEnv* env, jsize length, jclass element_class,
jobject initial_element = nullptr);
static StatusOr<ScopedLocalRef<jbyteArray>> NewByteArray(JNIEnv* env,
jsize length);
static StatusOr<ScopedLocalRef<jintArray>> NewIntArray(JNIEnv* env,
jsize length);
static StatusOr<ScopedLocalRef<jstring>> NewStringUTF(JNIEnv* env,
const char* bytes);
static StatusOr<ScopedLocalRef<jfloatArray>> NewFloatArray(JNIEnv* env,
jsize length);
static StatusOr<jsize> GetArrayLength(JNIEnv* env, jarray array);
static Status SetObjectArrayElement(JNIEnv* env, jobjectArray array,
jsize index, jobject val);
static Status GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start,
jsize len, jbyte* buf);
static Status SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start,
jsize len, const jbyte* buf);
static Status SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start,
jsize len, const jint* buf);
static Status SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start,
jsize len, const jfloat* buf);
// Call* methods.
TC3_DEFINE_VARIADIC_SCOPED_LOCAL_REF_ENV_METHOD(CallObjectMethod, jobject,
jobject, TC3_JNI_NO_CHECK);
TC3_DEFINE_VARIADIC_SCOPED_LOCAL_REF_ENV_METHOD(CallStaticObjectMethod,
jobject, jclass,
TC3_JNI_NO_CHECK);
static Status CallVoidMethod(JNIEnv* env, jobject object, jmethodID method_id,
...);
static StatusOr<bool> CallBooleanMethod(JNIEnv* env, jobject object,
jmethodID method_id, ...);
static StatusOr<int32> CallIntMethod(JNIEnv* env, jobject object,
jmethodID method_id, ...);
static StatusOr<int64> CallLongMethod(JNIEnv* env, jobject object,
jmethodID method_id, ...);
static StatusOr<float> CallFloatMethod(JNIEnv* env, jobject object,
jmethodID method_id, ...);
static StatusOr<double> CallDoubleMethod(JNIEnv* env, jobject object,
jmethodID method_id, ...);
template <class T>
static StatusOr<T> CallStaticIntMethod(JNIEnv* env,
bool print_exception_on_error,
jclass clazz, jmethodID method_id,
...);
};
template <typename T>
StatusOr<ScopedLocalRef<T>> JniHelper::GetObjectArrayElement(JNIEnv* env,
jobjectArray array,
jsize index) {
TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
ScopedLocalRef<T> result(
reinterpret_cast<T>(env->GetObjectArrayElement(array, index)), env);
TC3_NO_EXCEPTION_OR_RETURN;
return result;
}
template <class T>
StatusOr<T> JniHelper::CallStaticIntMethod(JNIEnv* env,
bool print_exception_on_error,
jclass clazz, jmethodID method_id,
...) {
va_list args;
va_start(args, method_id);
jint result = env->CallStaticIntMethodV(clazz, method_id, args);
va_end(args);
if (JniExceptionCheckAndClear(env, print_exception_on_error)) {
return {Status::UNKNOWN};
}
return result;
}
// Converts Java byte[] object to std::string.
StatusOr<std::string> JByteArrayToString(JNIEnv* env, jbyteArray array);
// Converts Java String object to UTF8-encoded std::string.
StatusOr<std::string> JStringToUtf8String(JNIEnv* env, jstring jstr);
} // namespace libtextclassifier3
#endif // LIBTEXTCLASSIFIER_UTILS_JAVA_JNI_HELPER_H_