编写并包括C++;Android JNI应用程序的类 我对使用Android NDK和JNI很有经验,但在java和C++方面都有经验。我正在尝试构造一个MWE,它表明在本地运行循环方法比在java类上运行要快。我导入了样本,转换了JNI代码,与C++兼容,并按照预期运行。
在同一个项目中,我删除了示例代码并重新开始,但没有更改构建设置。为了比较性能,我创建了两个相同的类,它们对整数和数组执行循环操作。我有一个Java类,叫做“代码> TESTRAPHELMADS< /COD>”和“C++类(通过<代码> .h /代码>和编写并包括C++;Android JNI应用程序的类 我对使用Android NDK和JNI很有经验,但在java和C++方面都有经验。我正在尝试构造一个MWE,它表明在本地运行循环方法比在java类上运行要快。我导入了样本,转换了JNI代码,与C++兼容,并按照预期运行。,android,gradle,android-ndk,java-native-interface,Android,Gradle,Android Ndk,Java Native Interface,在同一个项目中,我删除了示例代码并重新开始,但没有更改构建设置。为了比较性能,我创建了两个相同的类,它们对整数和数组执行循环操作。我有一个Java类,叫做“代码> TESTRAPHELMADS< /COD>”和“C++类(通过 .h /代码>和 .CPP< /Case>文件),称为 TestCLSASSCPP 类。这些类别如下: public class TestClassJava { // Fields private int id; private int[] array; // Co
public class TestClassJava {
// Fields
private int id;
private int[] array;
// Constructor
public TestClassJava(int start_id) { // etc... }
// Methods
public void incrementId() { // etc... }
public void labelArray() { // etc... }
public void loop() {
while (id < 5000000) {
incrementId();
labelArray();
}
}
}
然后是.cpp
#include "TestClassCpp.h"
// Constructor / Destructor
TestClassCpp::TestClassCpp(int start_id) { // etc... }
TestClassCpp::~TestClassCpp() { }
// Methods
void TestClassCpp::incrementId() { // etc... }
void TestClassCpp::labelArray() { // etc... }
void TestClassCpp::loop() {
while (id < 5000000) {
incrementId();
labelArray();
}
}
nativeloper()
在testclasswrapper.cpp
文件中声明为
JNIEXPORT void JNICALL
Java_com_example_jnimwe_MainActivity_nativeLooper(JNIEnv *env, jobject instance) {
// Get class
jclass cls = env->FindClass("TestClassCpp");
// Get method id of constructor
jmethodID constructor_method_id = env->GetMethodID(cls, "<init>", "(I)V" );
// Instantiate object from C++ definition
jobject jobj = env->NewObject(cls,constructor_method_id);
// Get loop method id from object
jmethodID mid = env->GetMethodID(cls,"loop","()V");
// Loop
env->CallVoidMethod(jobj,mid);
}
JNIEXPORT void JNICALL
Java_com_示例_jnimwe_main活动_nativeloper(JNIEnv*env,jobject实例){
//上课
jclass cls=env->FindClass(“TestClassCpp”);
//获取构造函数的方法id
jmethodID构造函数_method_id=env->GetMethodID(cls,”,“(I)V”);
/从C++定义实例化对象
jobject jobj=env->NewObject(cls,构造函数\方法\ id);
//从对象获取循环方法id
jmethodID mid=env->GetMethodID(cls,“loop”和“()V”);
//环路
env->CallVoidMethod(jobj,mid);
}
应用程序构建和部署了类,但找不到具有jclass cls=env->FindClass(“TestClassCpp”)的类代码>。我在build.gradle
文件中添加了moduleName
作为testclasswrapper
错误是
JNI在应用程序中检测到错误:调用JNI GetMethodID时,在未知的抛出位置抛出挂起的异常“java.lang.ClassNotFoundException”
06-23 16:07:14.617 12131-12131/com.example.jnimwe A/art:art/runtime/check_jni.cc:64]调用GetMethodID
很明显,它不知道这门课。因此,我假设在构建时,gradle在构建库时没有包含类定义,只是从一个文件(testclasswrapper.cpp
)构建,而不是搜索所有文件并构建和链接所有文件。在
testclasswrapper.cpp`中添加一个#include“/TestClassCpp.h”时,该选项会变灰,因此类的定义不会以这种方式包含
据我所知,最初的hello jni
示例使用ndk构建。类似的答案都涉及名为Application.mk
的makefilehello jni示例中没有生成文件,因此我的示例中也没有生成文件。我如何告诉gradle构建我创建的类并将其链接到我正在加载的库中?我不确定是否遗漏了什么,但从上面提到的内容来看,Java中似乎没有TestClassCpp
类;这就是env->FindClass(“TestClassCpp”)
调用试图做的事情。您是否打算在FindClass()
调用中查找TestClassJava
?感谢@zenzelezz的回复。很抱歉,这个问题太长,很难理解。没错,我没有java中的TestCLSASPP,我已经在C++中定义并实现了整个类。你是说FindClass()
只查找Java类吗?在这种情况下,我如何在JNI CPP文件中实例化C++类?是的,<代码> FUNCHACKE()/<代码>,代码> java方法()/代码>等都是为了让本机代码告诉Java在java类/对象上工作。在本机代码中,您的工作方式与不使用Java时相同。在您的例子中,我假设基本上TestClassCpp c(x);c、 loop()代码>好的,谢谢。JNI环境显然让我对应该使用的语法感到困惑。当我用TestClassCpp*_c=newtestclasscpp(0)替换JNI循环例程时,编译和运行良好_c->loop()但是本机方法比Java实例化和循环慢,这有点令人失望。考虑到我没有在nativeloper()
方法中进行任何接口调用,对@zenzelezz有什么想法?顺便说一句,如果你想把你的建议变成一个答案,如果你愿意的话,我可以接受。很难猜测为什么一个比另一个快,而看不到incrementId()
和labelArray()
,他们可能在技术上在引擎盖下进行非常不同的操作-直接比较并不一定容易。另外,您如何度量这两个类的时间?我不确定是否遗漏了什么,但从您上面提到的内容来看,您似乎没有Java中的TestClassCpp
类;这就是env->FindClass(“TestClassCpp”)
调用试图做的事情。您是否打算在FindClass()
调用中查找TestClassJava
?感谢@zenzelezz的回复。很抱歉,这个问题太长,很难理解。没错,我没有java中的TestCLSASPP,我已经在C++中定义并实现了整个类。你是说FindClass()
只查找Java类吗?在这种情况下,我如何在JNI CPP文件中实例化C++类?是的,<代码> FUNCHACKE()/<代码>,代码> java方法()/代码>等都是为了让本机代码告诉Java在java类/对象上工作。在本机代码中,您的工作方式与不使用Java时相同。在您的例子中,我假设基本上TestClassCpp c(x);c、 loop()代码>好的,谢谢。JNI环境显然让我对应该使用的语法感到困惑。当我用TestClassCpp*_c=newtestclasscpp(0)替换JNI循环例程时,编译和运行良好_c->loop()但是本机方法比Java实例化慢
static {
System.loadLibrary("testclasswrapper");
}
public native void nativeLooper();
JNIEXPORT void JNICALL
Java_com_example_jnimwe_MainActivity_nativeLooper(JNIEnv *env, jobject instance) {
// Get class
jclass cls = env->FindClass("TestClassCpp");
// Get method id of constructor
jmethodID constructor_method_id = env->GetMethodID(cls, "<init>", "(I)V" );
// Instantiate object from C++ definition
jobject jobj = env->NewObject(cls,constructor_method_id);
// Get loop method id from object
jmethodID mid = env->GetMethodID(cls,"loop","()V");
// Loop
env->CallVoidMethod(jobj,mid);
}