在 Android Studio 3 中设置 JNI
Setting up JNI in Android Studio 3
我在我正在做的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
时都必须重新计算和重新定义程序中保持不变的其他变量。
我在堆栈溢出上遇到了这个答案(除了它显示了我正在尝试做的事情的示例之外,它与这个问题无关),它显示了使用 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中可能吗?
您是 100% 正确的,一些 JNI 值需要缓存和重用。类引用和方法 ID 就是很好的例子。请记住,FindClass()返回一个本地引用,因此您需要为保存在缓存中的每个类提供NewGlobalRef()。
Android Studio 无法帮助我们进行此设置,而且我不知道可靠的工具可以为我们进行此类重构。您可以从开源代码中学习良好的实践,例如从WebRTC JNI包装器或Spotify JNI助手。
Android Studio 只能跟踪本机方法,而不能跟踪缓存的对象、转换等。
相关文章:
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 在C++/Linux中设置单调时钟的一些技巧
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 嵌套在类中时无法设置成员数据
- 需要帮助设置在C++中使用的Potrace
- 如何在自删除后将对象设置为nullptr
- 将指针设置为"nullptr"并不能防止双重删除?
- 如何在Ubuntu中使用cmake设置qt4
- ld:bind_at_load和-bitcode_bundle(Xcode设置ENABLE_bitcode=YES)不能
- 如何在boost beast http请求中设置http头
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 设置 JVM 通过 JNI 初始化时创建的线程数
- 如何在C++(JNI)中设置正在运行的JVM的类路径
- 将对象传递给 Java C++与使用 JNI 逐个设置对象参数
- 无法从JNI设置Java Int数组字段
- 在 Android Studio 3 中设置 JNI
- 如何通过 JNI 设置 java 类的双精度/整数类型的值
- 如何在安卓JNI中设置文件路径
- 在ndk{}中使用moduleName时如何设置JNI依赖