使本机代码访问java方法和数据成员
make native code access java methods and data members
我正在开发一个带有本地代码的android项目,该项目应该更新对象中的List和其他一些布尔变量。
考虑以下代码
我代码中的一些java类看起来像:
class ReturnObject
{
boolean a, b;
public List<String[]> listA;
}
public class foo
{
public native void someFunction(ReturnObject returnObject);
}
本地代码看起来像:
JNIEXPORT void JNICALL Java_com_example_androidtest_TestActivity_someFunction
(JNIEnv * env, jobject jObj, jobject returnObject) {
std::string f = "foo";
// missing code here
// returnObject.add(f) // add like in java
}
如何设置布尔变量的值?
对于List(知道我在本机代码中的数据存储为std::string
),我如何从本机代码调用List类的add(String[] string
)方法?
以下是设置布尔值的示例代码,遵循相同的准则调用列表的add
方法。
#include <stdio.h>
#include <jni.h>
#include "com_example_Foo.h"
JNIEXPORT void JNICALL Java_com_example_Foo_someFunction
(JNIEnv *env, jobject object, jobject returnObject)
{
jclass clzReturnObject = env->FindClass("com/example/ReturnObject");
jfieldID fieldA = env->GetFieldID(clzReturnObject, "a", "Z");
jfieldID fieldB = env->GetFieldID(clzReturnObject, "b", "Z");
env->SetBooleanField(returnObject, fieldA, true);
if (env->ExceptionCheck()) {
fprintf(stderr, "error set boolean for a");
env->ExceptionDescribe();
}
env->SetBooleanField(returnObject, fieldB, false);
if (env->ExceptionCheck()) {
fprintf(stderr, "error set boolean for b");
env->ExceptionDescribe();
}
jfieldID fieldListID = env->GetFieldID(clzReturnObject, "list",
"Ljava/util/List;");
jobject listObject = env->GetObjectField(returnObject, fieldListID);
jclass clzList = env->FindClass("java/util/List");
jmethodID addMethodID = env->GetMethodID(clzList, "add",
"(Ljava/lang/Object;)Z");
jclass clzString = env->FindClass("java/lang/String");
jstring initElement = env->NewStringUTF("0000");
jobjectArray toAdd = env->NewObjectArray(10, clzString, initElement);
if (env->ExceptionCheck()) {
fprintf(stderr, "error create string array");
env->ExceptionDescribe();
}
env->CallBooleanMethod(listObject, addMethodID, toAdd);
env->DeleteLocalRef(initElement);
}
以下是java代码
public class Foo {
static {
System.loadLibrary("Foo");
}
public static void main(String[] args) {
ReturnObject returnObject = new ReturnObject();
returnObject.list = new ArrayList<>();
Foo foo = new Foo();
foo.someFunction(returnObject);
System.out.println("size is " + returnObject.list.size());
foo.someFunction(returnObject);
System.out.println("size is " + returnObject.list.size());
foo.someFunction(returnObject);
System.out.println("size is " + returnObject.list.size());
// we have three element added from JNI
for (String string : returnObject.list.get(2)) {
System.out.println(string);
}
}
public native void someFunction(ReturnObject returnObject);
}
这里有一个调用字符串构造函数在JNI中创建jstring的例子。
jbyteArray initValue = env->NewByteArray(10);
env->SetByteArrayRegion(initValue, 0, 9, (const signed char*)"ABCDEFG");
jstring enc = env->NewStringUTF("UTF-8");
jclass clzString = env->FindClass("java/lang/String");
jmethodID cMethodID = env->GetMethodID(clzString, "<init>", "([BLjava/lang/String;)V");
jstring result = reinterpret_cast<jstring>(env->NewObject(clzString, cMethodID, initValue, enc));
以下是从JNI读取EditText
文本的示例。
void Java_com_example_foo_MainActivity_someFunction(JNIEnv* env, jobject object,
jstring objString, jobject objEditText) {
__android_log_print(ANDROID_LOG_INFO, "Foo", "%sn", "JNI call");
// get edittext value
jclass clzEditText = env->GetObjectClass(objEditText);
jmethodID methodGetText = env->GetMethodID(clzEditText, "getText", "()Landroid/text/Editable;");
jobject objEditable = env->CallObjectMethod(objEditText, methodGetText);
jclass clzEditable = env->GetObjectClass(objEditable);
jmethodID methodToString = env->GetMethodID(clzEditable, "toString", "()Ljava/lang/String;");
jstring editText = reinterpret_cast<jstring>(env->CallObjectMethod(
objEditable, methodToString));
jboolean isCopy = true;
__android_log_print(ANDROID_LOG_INFO, "Foo", "From java: %sn", env->GetStringUTFChars(editText, &isCopy));
}
假设在应用程序的MainActivity
中声明了一个jni。
private native void someFunction(String s, EditText editText);
我没有找到一个好的解决方案来直接从JNI设置String
。如果您想在JNI中操作String
,您可以将结果从返回值传递给Java。
private native String Foo();
相关文章:
- C++ 使用派生类方法更改基类数据成员
- 将私有数据成员作为默认参数传递给该类的公共方法时出错
- 在不编写显式 setter 的情况下修改私有类数据成员的便捷方法是什么?模板有用吗?
- 将非静态数据成员作为默认参数传递给方法
- 使用来自基类方法的派生类数据成员
- 如何仅通过类方法修改类公共数据成员
- 子类是否也在 c++ 中继承私有数据成员?但通过超类的公共方法访问
- 我如何调用我的3个数据成员中每个人的设置方法,然后显示由我的设置方法设置的值
- 如何在类中的其他方法中访问私有数据成员 2D 数组
- 是C 静态对象中类的静态数据成员和静态方法
- 将数据从构造函数传输回调用方法时更改数据成员
- 比较来自同一类型的两个对象的数据成员的最简单方法
- 为具有一个数字数据成员的类定义所有比较运算符的方便方法
- 使本机代码访问java方法和数据成员
- 在派生类中使用提取运算符(>>)的方法以及在C++中处理静态数据成员的方法
- 类静态方法访问其静态数据成员
- 类方法访问其数据成员
- 将数据成员的生存期限制为一个方法
- 有关C++/组件数据布局、数据成员访问、方法的一般问题
- 返回对类静态数据成员的引用的正确方法是什么?(我正在使用Qt,以防万一它有所作为)