JNI 的基本问题就是解决 Java 和 C++ 代码互相调用的通信问题,在 C++ 代码编写过程中最大的问题莫过于适应其中的代码编写规则,C++调用或是返回的内容必须遵守 JVM 和 C++ 代码的通信规则。
C++ 调用 Java 的一般步骤如下:
-
获得类:
- jclass cls = env->FindClass("com/ldq/Student");
- cls 可认为是类的句柄
- "com/ldq/Student" 就是类文件,注意不能用 "com.ldq.Student"
-
获得方法:
- jmethodID mid = env->GetMethodID(cls,"<init>","()V");
- 以上为构造函数,参数是 "<init>" "()V"
- jmethodID mid = env->GetMethodID(cls,"getAge","()I");
-
以上为类的方法,第一个参数是类句柄,第二个参数是方法名字,第三个参数是签名标识
Java类型
|
符号 |
boolean |
Z |
byte
|
B |
char
|
C |
short |
S |
int |
I |
long |
L |
float |
F |
double
|
D |
void
|
V |
objects对象 |
Lfully-qualified-class-name; L类名; |
Arrays数组 |
[array-type [数组类型 |
methods方法 |
(argument-types)return-type(参数类型)返回类型 |
-
获得对象:
- jobject obj=env->NewObject(cls,mid);
- 以上便获得了一个对象的句柄
-
获得对象成员变量:
- jfieldID fid=env->GetFieldID(cls,"age","I");
- 以上和获得类方法差不多
-
操作成员变量:
- jint a=env->GetIntField(obj,mid);
- age=age+10;
- env->SetIntField(obj,fid,a);
-
返回:
下面是本人练习的例子
package com.ldq.list;
import java.util.List;
public class ExList {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("-------WifiManager.test()");
System.out.println(WifiManager.test());
System.out.println("-------WifiManager.testArray()");
String[] s1 = WifiManager.testArray();
for (int i = 0; i < s1.length; i++) {
System.out.println(s1[i]);
}
System.out.println("-------WifiManager.testObject()");
System.out.println(WifiManager.testObject().ssid);
System.out.println(WifiManager.testObject().mac);
System.out.println(WifiManager.testObject().level);
System.out.println("-------WifiManager.getScanResultsA()");
ScanResult[] s2 = WifiManager.getScanResultsA();
for (int i = 0; i < s2.length; i++) {
System.out.println(s2[i].ssid);
System.out.println(s2[i].mac);
System.out.println(s2[i].level);
}
System.out.println("-------WifiManager.getScanResults()");
List<ScanResult> list = WifiManager.getScanResults();
System.out.println(list.get(0).ssid);
System.out.println(list.get(0).mac);
System.out.println(list.get(0).level);
}
}
package com.ldq.list;
public class ScanResult {
String ssid;
String mac;
int level;
public ScanResult() {
}
public ScanResult(String ssid, String mac, int level) {
this.ssid = ssid;
this.mac = mac;
this.level = level;
}
}
package com.ldq.list;
import java.util.List;
public class WifiManager {
static {
System.loadLibrary("wifi");
}
public native static String test();
public native static String[] testArray();
public native static ScanResult testObject();
public native static ScanResult[] getScanResultsA();
public native static List<ScanResult> getScanResults();
}
#include <jni.h>
#include "com_ldq_list_WifiManager.h"
/*
* Class: com_ldq_list_WifiManager
* Method: test
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_ldq_list_WifiManager_test (JNIEnv *env, jclass cls)
{
return env->NewStringUTF("hello");
}
/*
* Class: com_ldq_list_WifiManager
* Method: testArray
* Signature: ()[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_com_ldq_list_WifiManager_testArray (JNIEnv *env, jclass cls)
{
jobjectArray ret;
int i;
char *message[5]= {"first",
"second",
"third",
"fourth",
"fifth"};
ret= (jobjectArray)env->NewObjectArray(5,
env->FindClass("java/lang/String"),
env->NewStringUTF(""));
for(i=0;i<5;i++) {
env->SetObjectArrayElement(
ret,i,env->NewStringUTF(message[i]));
}
return(ret);
}
/*
* Class: com_ldq_list_WifiManager
* Method: testObject
* Signature: ()Lcom/ldq/list/ScanResult;
*/
JNIEXPORT jobject JNICALL Java_com_ldq_list_WifiManager_testObject (JNIEnv *env, jclass cls)
{
jclass m_cls = env->FindClass("com/ldq/list/ScanResult");
jmethodID mid = env->GetMethodID(m_cls,"<init>","()V");
jobject obj = env->NewObject(m_cls,mid);
jfieldID fid_ssid = env->GetFieldID(m_cls,"ssid","Ljava/lang/String;");
jfieldID fid_mac = env->GetFieldID(m_cls,"mac","Ljava/lang/String;");
jfieldID fid_level = env->GetFieldID(m_cls,"level","I");
env->SetObjectField(obj,fid_ssid,env->NewStringUTF("AP1"));
env->SetObjectField(obj,fid_mac,env->NewStringUTF("00-11-22-33-44-55"));
env->SetIntField(obj,fid_level,-66);
return obj;
}
/*
* Class: com_ldq_list_WifiManager
* Method: getScanResultsA
* Signature: ()[Lcom/ldq/list/ScanResult;
*/
JNIEXPORT jobjectArray JNICALL Java_com_ldq_list_WifiManager_getScanResultsA (JNIEnv *env, jclass cls)
{
jclass cls_array=env->FindClass("java/lang/Object");
jobjectArray obj_array=env->NewObjectArray(2,cls_array,0);
jclass cls_obj = env->FindClass("com/ldq/list/ScanResult");
jmethodID m = env->GetMethodID(cls_obj,"<init>","()V");
jfieldID fid_ssid = env->GetFieldID(cls_obj,"ssid","Ljava/lang/String;");
jfieldID fid_mac = env->GetFieldID(cls_obj,"mac","Ljava/lang/String;");
jfieldID fid_level = env->GetFieldID(cls_obj,"level","I");
for(int i=0;i<2;i++)
{
jobject obj=env->NewObject(cls_obj,m);
jobject o1=env->NewStringUTF("AP2");
env->SetObjectField(obj,fid_ssid,o1);
jobject o2=env->NewStringUTF("22-22-22-22-22-22");
env->SetObjectField(obj,fid_mac,o2);
env->SetIntField(obj,fid_level,-66);
env->SetObjectArrayElement(obj_array,i,obj);
}
return obj_array;
}
/*
* Class: com_ldq_list_WifiManager
* Method: getScanResults
* Signature: ()Ljava/util/List;
*/
JNIEXPORT jobject JNICALL Java_com_ldq_list_WifiManager_getScanResults (JNIEnv *env, jclass cls)
{
jclass m_cls_list = env->FindClass("java/util/ArrayList");
jmethodID m_mid_list = env->GetMethodID(m_cls_list,"<init>","()V");
jobject m_obj_list = env->NewObject(m_cls_list,m_mid_list);
jmethodID m_mid_add = env->GetMethodID(m_cls_list,"add","(Ljava/lang/Object;)Z");
jclass m_cls_result = env->FindClass("com/ldq/list/ScanResult");
jmethodID m_mid_result = env->GetMethodID(m_cls_result,"<init>","()V");
jobject m_obj_result = env->NewObject(m_cls_result,m_mid_result);
jfieldID m_fid_1 = env->GetFieldID(m_cls_result,"ssid","Ljava/lang/String;");
jfieldID m_fid_2 = env->GetFieldID(m_cls_result,"mac","Ljava/lang/String;");
jfieldID m_fid_3 = env->GetFieldID(m_cls_result,"level","I");
env->SetObjectField(m_obj_result,m_fid_1,env->NewStringUTF("AP6"));
env->SetObjectField(m_obj_result,m_fid_2,env->NewStringUTF("66-66-66-66-66-66"));
env->SetIntField(m_obj_result,m_fid_3,-66);
env->CallBooleanMethod(m_obj_list,m_mid_add,m_obj_result);
return m_obj_list;
}
分享到:
相关推荐
然后,你需要在JNI中定义一个函数,接收Java对象作为参数,处理后返回自定义对象。这通常涉及到JNI的`NewObject`函数,用于创建Java对象。例如: ```cpp jobject createCustomObject(JNIEnv *env, int id, const ...
对象数组的处理涉及到对Java虚拟机(JVM)的内存管理和类型转换的理解。 1. **创建本地方法** 在Java类中,我们可以声明一个本地方法,使用`native`关键字,例如: ```java public class JniObjArrayExample { ...
`JNI对象的操作.txt`可能会涵盖更多基本对象的创建和访问,而`JNI字符串处理.txt`将详细讲解String对象的各种操作。`jni数据处理.txt`可能涉及不同类型的数据转换,如整型、浮点型和数组的处理。 总的来说,JNI提供...
本主题主要关注如何通过JNI从C++代码中获取并操作Java对象。 1. **JNI基础** JNI是Java平台标准的一部分,为开发者提供了在本地代码(如C或C++)中调用Java方法和字段,以及创建和操作Java对象的能力。JNI接口包括...
在这个主题中,我们将深入探讨如何在JNI中操作ArrayList对象并添加一个int类型的数据。 首先,我们需要理解ArrayList在Java中的本质。ArrayList是Java集合框架中的一个重要类,它实现了List接口,用于存储可变大小...
在本场景中,"JNI创建java对象"指的是利用JNI技术在C/C++原生代码中创建和操作Java对象。JNI在Android开发中尤其重要,因为Android系统的主要编程语言是Java,但为了实现高性能计算或调用操作系统底层功能,开发者...
总结来说,通过JNI将Java对象传递到C代码,需要理解JNI的API,正确处理Java对象的生命周期,并确保在C代码中安全地操作这些对象。这既是一个挑战,也是提升程序性能和功能的重要手段。在实际开发中,应充分考虑跨...
对于存储自定义对象(如点对象Point)的情况,我们需要先定义一个JNI接口,该接口声明了一个方法来处理List的创建和添加元素。 1. **JNI接口声明**: 在Java层,我们需要创建一个JNI接口,其中包含要由C/C++实现的...
本示例"android jni 传递对象的demo"聚焦于一个特定的应用场景:在Java层和C/C++层之间传递对象。 首先,我们要理解在Java和C/C++之间传递对象的挑战。Java对象在JVM(Java虚拟机)中以引用的形式存在,而C/C++则不...
传递自定义Java对象到JNI层则相对复杂,因为需要处理对象引用和对象内部的数据。首先,你需要使用`FindClass`方法获取Java类的本地表示,然后通过`NewObject`创建实例。对于传递的对象,需要定义对应的结构体来存储...
在Android开发中,JNI常用于提升性能,处理特定硬件操作,或者调用已有的C/C++库。本文将深入探讨如何使用JNI调用Java对象和数组,并在C/C++层进行操作,以及如何通过监听器传递数据。 首先,我们要了解JNI的基本...
然而,处理复杂对象,如字符串、数组或自定义类,需要更多的步骤。对于Java字符串,我们可以使用`env->NewStringUTF`创建一个新的本地字符串,或使用`env->GetStringUTFChars`获取字符串的UTF-8表示。例如: ```c++...
至于支持汉字的传递和类的传递,这可能是指在JNI中处理包含汉字的字符串,以及将Java类的对象作为参数传递给本地方法。处理汉字需要确保编码正确,通常使用UTF-8编码。传递Java类的对象则需要使用JNI的NewGlobalRef...
在实际开发中,还需要注意一些细节,比如错误处理、内存管理(Java对象在本地代码中使用需要通过JNI函数创建和释放)、线程安全问题等。同时,由于涉及到跨语言和跨平台,理解JNI的工作原理和正确使用JNI头文件至关...
在本示例中,我们关注的是如何在JNI中使用`jobjectArray`来处理Java对象数组。 `jobjectArray`是JNI中的一个类型,它代表了Java世界中的对象数组。使用`jobjectArray`,我们可以从本地代码创建、访问和修改Java对象...
3. **处理Java数组**: Delphi代码可以操作Java数组,无论是基本类型还是对象数组。 4. **注册本地方法**:在Java代码中,通过JNI注册本地方法,使得Java能够调用到Delphi实现的函数。 5. **内存管理**:JNI提供了在...
2. 引用类型:JNI处理Java的对象引用使用` jobject`, `jclass`, `jstring`, `jarray`, `jobjectArray`, `jbooleanArray`, `jbyteArray`, `jcharArray`, `jshortArray`, `jintArray`, `jlongArray`, `jfloatArray`, `...
本文将深入探讨Android JNI中的异常处理机制,这是开发者在进行跨语言编程时必须掌握的关键技能。 ### JNI异常处理基础 1. **Java异常到C++的转换**:当Java代码抛出异常时,如果这个异常在JNI函数内部没有被捕获...
综上所述,Java Activity通过JNI与本地代码进行JSON数据交换涉及到序列化/反序列化、JNI接口定义、本地代码实现、错误处理和性能优化等多个环节。理解和熟练掌握这些步骤对于开发高效的Android应用至关重要。
开发者一般不需要直接处理`jni_md.h`,因为`jni.h`已经处理了所有跨平台的兼容性问题。 使用JNI时,开发流程通常包括以下步骤: 1. **编写本地方法**:在Java类中声明native方法,并使用`native`关键字。 2. **生成...