/* Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. 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. */ #pragma once #include #include // NOLINT #include // NOLINT #include "lite/api/light_api.h" #include "lite/api/paddle_api.h" #include "lite/api/paddle_place.h" namespace paddle { namespace lite_api { inline std::string jstring_to_cpp_string(JNIEnv *env, jstring jstr) { // In java, a unicode char will be encoded using 2 bytes (utf16). // so jstring will contain characters utf16. std::string in c++ is // essentially a string of bytes, not characters, so if we want to // pass jstring from JNI to c++, we have convert utf16 to bytes. if (!jstr) { return ""; } const jclass stringClass = env->GetObjectClass(jstr); const jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B"); const jbyteArray stringJbytes = (jbyteArray)env->CallObjectMethod( jstr, getBytes, env->NewStringUTF("UTF-8")); size_t length = (size_t)env->GetArrayLength(stringJbytes); jbyte *pBytes = env->GetByteArrayElements(stringJbytes, NULL); std::string ret = std::string(reinterpret_cast(pBytes), length); env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT); env->DeleteLocalRef(stringJbytes); env->DeleteLocalRef(stringClass); return ret; } inline jstring cpp_string_to_jstring(JNIEnv *env, std::string str) { auto *data = str.c_str(); jclass strClass = env->FindClass("java/lang/String"); jmethodID strClassInitMethodID = env->GetMethodID(strClass, "", "([BLjava/lang/String;)V"); jbyteArray bytes = env->NewByteArray(strlen(data)); env->SetByteArrayRegion( bytes, 0, strlen(data), reinterpret_cast(data)); jstring encoding = env->NewStringUTF("UTF-8"); jstring res = (jstring)( env->NewObject(strClass, strClassInitMethodID, bytes, encoding)); env->DeleteLocalRef(strClass); env->DeleteLocalRef(encoding); env->DeleteLocalRef(bytes); return res; } inline jfloatArray cpp_array_to_jfloatarray(JNIEnv *env, const float *buf, int64_t len) { jfloatArray result = env->NewFloatArray(len); env->SetFloatArrayRegion(result, 0, len, buf); return result; } inline jbyteArray cpp_array_to_jbytearray(JNIEnv *env, const int8_t *buf, int64_t len) { jbyteArray result = env->NewByteArray(len); env->SetByteArrayRegion(result, 0, len, buf); return result; } inline jintArray cpp_array_to_jintarray(JNIEnv *env, const int *buf, int64_t len) { jintArray result = env->NewIntArray(len); env->SetIntArrayRegion(result, 0, len, buf); return result; } inline jlongArray cpp_array_to_jlongarray(JNIEnv *env, const int64_t *buf, int64_t len) { jlongArray result = env->NewLongArray(len); env->SetLongArrayRegion(result, 0, len, buf); return result; } inline jlongArray int64_vector_to_jlongarray(JNIEnv *env, const std::vector &vec) { jlongArray result = env->NewLongArray(vec.size()); jlong *buf = new jlong[vec.size()]; for (size_t i = 0; i < vec.size(); ++i) { buf[i] = (jlong)vec[i]; } env->SetLongArrayRegion(result, 0, vec.size(), buf); delete[] buf; return result; } inline std::vector jlongarray_to_int64_vector(JNIEnv *env, jlongArray dims) { int dim_size = env->GetArrayLength(dims); jlong *dim_nums = env->GetLongArrayElements(dims, nullptr); std::vector dim_vec(dim_nums, dim_nums + dim_size); env->ReleaseLongArrayElements(dims, dim_nums, 0); return dim_vec; } /** * Converts Java com.baidu.paddle.lite.Place to c++ paddle::lite_api::Place. */ inline Place jplace_to_cpp_place(JNIEnv *env, jobject java_place) { jclass place_jclazz = env->GetObjectClass(java_place); jmethodID target_method = env->GetMethodID(place_jclazz, "getTargetInt", "()I"); jmethodID precision_method = env->GetMethodID(place_jclazz, "getPrecisionInt", "()I"); jmethodID data_layout_method = env->GetMethodID(place_jclazz, "getDataLayoutInt", "()I"); jmethodID device_method = env->GetMethodID(place_jclazz, "getDevice", "()I"); int target = env->CallIntMethod(java_place, target_method); int precision = env->CallIntMethod(java_place, precision_method); int data_layout = env->CallIntMethod(java_place, data_layout_method); int device = env->CallIntMethod(java_place, device_method); return Place(static_cast(target), static_cast(precision), static_cast(data_layout), device); } inline CxxConfig jcxxconfig_to_cpp_cxxconfig(JNIEnv *env, jobject jcxxconfig) { jclass cxxconfig_jclazz = env->GetObjectClass(jcxxconfig); jmethodID model_dir_method = env->GetMethodID(cxxconfig_jclazz, "getModelDir", "()Ljava/lang/String;"); jmethodID valid_places_method = env->GetMethodID( cxxconfig_jclazz, "getValidPlaces", "()[Lcom/baidu/paddle/lite/Place;"); CxxConfig config; jstring java_model_dir = (jstring)env->CallObjectMethod(jcxxconfig, model_dir_method); if (java_model_dir != nullptr) { std::string cpp_model_dir = jstring_to_cpp_string(env, java_model_dir); config.set_model_dir(cpp_model_dir); } jobject object_valid_places = env->CallObjectMethod(jcxxconfig, valid_places_method); jobjectArray *java_valid_places = reinterpret_cast(&object_valid_places); if (java_valid_places != nullptr) { int valid_place_count = env->GetArrayLength(*java_valid_places); std::vector cpp_valid_places; for (int i = 0; i < valid_place_count; ++i) { jobject jplace = env->GetObjectArrayElement(*java_valid_places, i); cpp_valid_places.push_back(jplace_to_cpp_place(env, jplace)); } config.set_valid_places(cpp_valid_places); } return config; } inline MobileConfig jmobileconfig_to_cpp_mobileconfig(JNIEnv *env, jobject jmobileconfig) { jclass mobileconfig_jclazz = env->GetObjectClass(jmobileconfig); MobileConfig config; // set model dir // NOTE: This is a deprecated API and will be removed in latter release. jmethodID model_dir_method = env->GetMethodID( mobileconfig_jclazz, "getModelDir", "()Ljava/lang/String;"); jstring java_model_dir = (jstring)env->CallObjectMethod(jmobileconfig, model_dir_method); if (java_model_dir != nullptr) { std::string cpp_model_dir = jstring_to_cpp_string(env, java_model_dir); config.set_model_dir(cpp_model_dir); } // set model from file jmethodID model_file_method = env->GetMethodID( mobileconfig_jclazz, "getModelFromFile", "()Ljava/lang/String;"); jstring java_model_file = (jstring)env->CallObjectMethod(jmobileconfig, model_file_method); if (java_model_file != nullptr) { std::string cpp_model_file = jstring_to_cpp_string(env, java_model_file); config.set_model_from_file(cpp_model_file); } // set model from buffer jmethodID model_buffer_method = env->GetMethodID( mobileconfig_jclazz, "getModelFromBuffer", "()Ljava/lang/String;"); jstring java_model_buffer = (jstring)env->CallObjectMethod(jmobileconfig, model_buffer_method); if (java_model_buffer != nullptr) { std::string cpp_model_buffer = jstring_to_cpp_string(env, java_model_buffer); config.set_model_from_buffer(cpp_model_buffer); } // set threads jmethodID threads_method = env->GetMethodID(mobileconfig_jclazz, "getThreads", "()I"); int threads = env->CallIntMethod(jmobileconfig, threads_method); config.set_threads(threads); // set power mode jmethodID power_mode_method = env->GetMethodID(mobileconfig_jclazz, "getPowerModeInt", "()I"); int power_mode = env->CallIntMethod(jmobileconfig, power_mode_method); config.set_power_mode(static_cast(power_mode)); return config; } } // namespace lite_api } // namespace paddle