我在我正在开发的Android Studio项目中使用JNI。目前,我有一个类似于此的C ++库。
#include <jni.h>
...
extern "C" {
JNIEXPORT jobject JNICALL Java_com_cerbyarms_cerbyarms_esra_camera_CameraActivity_FindFeatures(JNIEnv* env, jobject, jlong maskMat)
{
...
jclass rectClass = env->FindClass("org/opencv/core/Rect");
jmethodID rectID = env->GetMethodID(rectClass, "<init>", "(IIII)V");
return env->NewObject(rectClass, rectID, x, y, width, height);
}
}
这很有效。但是,它效率低下。每次运行时,rectClass都必须重新引用类,并且每次调用函数FindFeatures
时都必须重新计算并重新定义程序中保持不变的其他变量。
我遇到了这个answer on Stack Overflow(除了它显示了我正在尝试做的一个例子之外,它与此问题无关),它显示了使用JNI时本机文件的不同布局
看起来像这样
static jclass java_util_ArrayList;
static jmethodID java_util_ArrayList_;
jmethodID java_util_ArrayList_size;
jmethodID java_util_ArrayList_get;
jmethodID java_util_ArrayList_add;
static thread_local JNIEnv* env;
void init() {
java_util_ArrayList = static_cast<jclass>(env->NewGlobalRef(env->FindClass("java/util/ArrayList")));
java_util_ArrayList_ = env->GetMethodID(java_util_ArrayList, "<init>", "(I)V");
java_util_ArrayList_size = env->GetMethodID (java_util_ArrayList, "size", "()I");
java_util_ArrayList_get = env->GetMethodID(java_util_ArrayList, "get", "(I)Ljava/lang/Object;");
java_util_ArrayList_add = env->GetMethodID(java_util_ArrayList, "add", "(Ljava/lang/Object;)Z");
}
std::vector<std::string> java2cpp(jobject arrayList) {
jint len = env->CallIntMethod(arrayList, java_util_ArrayList_size);
std::vector<std::string> result;
result.reserve(len);
for (jint i = 0; i < len; i++) {
jstring element = static_cast<jstring>(env->CallObjectMethod(arrayList, java_util_ArrayList_get, i));
const char* pchars = env->GetStringUTFChars(element, nullptr);
result.emplace_back(pchars);
env->ReleaseStringUTFChars(element, pchars);
env->DeleteLocalRef(element);
}
}
这显示了一个原生文件,它具有昂贵且常量的变量,似乎只能声明和计算一次。
如何仅使用Android Studio IDE实现类似的功能?我不介意在Android Studio IDE设置中设置外部工具,但我不想在每次编译代码时都在Android Studio和CMD之间切换。
理想情况下,当Make Project
被击中时,这一切都可以正确处理。这可以在Android Studio 3中使用吗?
答案 0 :(得分:1)
你100%正确,一些JNI值要求缓存和重用。类引用和方法ID是很好的例子。请记住 FindClass()会返回一个本地引用,因此您需要为缓存中保留的每个类提供 NewGlobalRef()。
Android Studio无法帮助我们完成此设置,而且我不知道可以为我们进行此类重构的可靠工具。您可以从开源代码中学习良好实践,例如:来自WebRTC JNI wrapper或Spotify JNI helpers。
Android Studio只能跟踪本机方法,而不是缓存对象,转换等。