ANDROID JNI中C和JAVA的参数如何传递

合集下载

JNI编程之如何传递参数和返回值

JNI编程之如何传递参数和返回值

首先要强调的是,native方法不但可以传递Java的基本类型做参数,还可以传递更复杂的类型,比如String,数组,甚至自定义的类。

这一切都可以在jni.h中找到答案。

1. Java基本类型的传递用过Java的人都知道,Java中的基本类型包括boolean,byte,char,short,int,long,float,double 这样几种,如果你用这几种类型做native方法的参数,当你通过javah -jni 生成.h文件的时候,只要看一下生成的.h文件,就会一清二楚,这些类型分别对应的类型是 jboolean,jbyte,jchar,jshort,jint,jlong,jfloat,jdouble 。

这几种类型几乎都可以当成对应的C++类型来用,所以没什么好说的。

2. String参数的传递Java的String和C++的string是不能对等起来的,所以处理起来比较麻烦。

先看一个例子,class Prompt {// native method that prints a prompt and reads a lineprivate native String getLine(String prompt);public static void main(String args[]) {Prompt p = new Prompt();String input = p.getLine("Type a line: ");System.out.println("User typed: " + input);}static {System.loadLibrary("Prompt");}}在这个例子中,我们要实现一个native方法String getLine(String prompt);读入一个String参数,返回一个String值。

Android中JNI的使用之一:Java原生JNI的使用、javah指令的使用以及图解教材

Android中JNI的使用之一:Java原生JNI的使用、javah指令的使用以及图解教材

Android中JNI的使用之一:Java原生JNI的使用、javah指令的使用以及图解教材Java Nativie Interface(JNI,中文名称Java本地接口)标准时Java平台的一部分,它允许Java代码和其他语言写得代码进行交互。

JNI是本地编程接口,它使得Java虚拟机(VM)内部运行的Java代码能够用其他编程语言(如C、C++和汇编语言)编写的应用程序和库进行交互操作。

JNI的主要用途是为了对硬件进行访问以及追求高效率或可重用C/C++库。

Android系统中采用了JNI的方式来调用C/C++方法,然而,在Android系统里进一步加强了Java JNI的使用,使JNI的调用更具有效率。

因此,总的来说,Android 系统里可以采用两种方式来使用JNI。

第一种:Java原生JNI,使用dll等动态链接库;第二种,Android加强版JNI,通过动态加载*.so链接库来进行JNI调用。

今天,我们分析第一种JNI使用方式,也称得上是JNI入门。

由于Java与其他编程语言采用的语法不同,为了让Java与C/C++库函数能进行通信,约定的一个参数类型映射如下:Java类型C/C++类型void voidjboolean booleanjint intjlong longjdouble doublejfloat floatjbyte jbytejchar charjshort shor上面的只是简单类型的一个映射,后面我们会完善其他参数类型的映射。

开发环境介绍(Windows下):Eclipse:主要用来创建Java工程MicrosoftVC++6.0:生成动态链接库供相应的Java文件加载一、使用Eclipse创建Java工程本例中,我们简单的创建了一个Java工程HelloBabyJNI,工程绝对路径位于E:\MyCode\AndroidCode\HelloBabyJNI路径下,主文件路径位于\src\lover\hellojni路径下(路径对后面的javah编译很重要)HelloBabyJNI.java文件如下:[java] view plaincopyprint?1.package com.lover.hellojni;2.3./**4. * 一个简单的Java JNI实例5. *6. */7.public class HelloBabyJNI {8.9./*10. * 静态构造函数,动态加载HelloBabyJNI动态库,其dll文件名为:HelloBabyJNI.dll --->由MSVC6.0软件创建11. */12.static {13. System.load("E:/HelloBabyJNI.dll"); // 可能需要 dll链接库的绝对存放路径14. }15.16./*17. * 在Java中注册需要调用的C/C++本地方法(native method),也就是需要C/C++来实现的方法18. */19.public native int add(int a, int b);20.21.// main方法,加载动态库来调用C/C++本地方法22.public static void main(String[] args) {23. HelloBabyJNI helloBabyJNI = new HelloBabyJNI();24.// 调用注册的add方法来得到返回值25.int result = helloBabyJNI.add(2, 3);26.// 输出27. System.out.println("after invoke the native method,the result is "+ result);28. }29.}2,编译HelloBabyJNI.java文件,生成HelloBabyJNI.class文件,位于路径\src\lover\hellojni\HelloBabyJNI.class3,使用javah指令编译HelloBabyJNI.class文件,生成Java与C/C++之间进行通信的约定接口,它规定了Java中nativemethod在C/C++的具体接口。

jni传类指针 -回复

jni传类指针 -回复

jni传类指针-回复JNI(Java Native Interface)是Java语言与本地(C或C++)代码进行交互的一种机制。

它提供了在Java虚拟机(JVM)中调用C或C++代码的能力,同时也能让本地代码调用Java代码。

在JNI中,通过使用类指针(Class Pointers)来对Java类进行引用。

本文将介绍有关JNI中类指针的知识。

在JNI中,类指针是一种特殊类型的指针,它指向Java中的类对象。

在C 或C++代码中,我们可以通过JNI函数`GetObjectClass`来获取一个类的指针。

比如下面这段代码:cppJNIEnv *env; JNI环境指针jobject obj; Java对象jclass cls = env->GetObjectClass(obj);上述代码中,`GetObjectClass`函数返回一个`jclass`类型的指针,指向`obj`对象所属的类。

一旦我们拥有了一个类的指针,我们就可以使用其他JNI函数来操作这个类。

例如,我们可以使用`GetMethodID`函数来获取类的方法ID,然后使用`CallVoidMethod`函数来调用这个方法。

下面是一个简单的示例:cppjmethodID methodId = env->GetMethodID(cls, "methodName", "()V");env->CallVoidMethod(obj, methodId);上述代码中,`GetMethodID`函数用于获取`cls`类中名为`methodName`的无参数、无返回值的方法的方法ID。

然后,`CallVoidMethod`函数用于调用该方法。

除了获取方法ID和调用方法,类指针还可以用于获取和设置类的字段。

我们可以使用`GetFieldID`函数获取字段ID,然后使用`Get<Type>Field`和`Set<Type>Field`函数来读取和修改字段的值。

jni实现原理

jni实现原理

jni实现原理介绍Java Native Interface(JNI)是Java标准库中的一个重要组成部分,它允许Java程序与本地代码进行交互。

通过JNI,Java程序可以调用本地代码中实现的方法,以及与本地代码共享数据。

JNI实现原理涉及到Java虚拟机(JVM)和本地代码(C/C++)之间的交互方式,本文将对其进行详细的探讨。

JNI基本概念在了解JNI实现原理之前,我们需要先了解一些相关的基本概念。

JNI库JNI库是一个包含本地方法的动态链接库(.dll或.so文件),它提供了与Java 程序进行交互的接口。

JNI库通过Java本地接口(JNI)提供给Java程序使用。

JNI接口JNI接口是一组函数,定义了Java虚拟机和本地代码之间的通信协议。

它规定了Java程序如何调用本地方法,以及本地方法如何返回结果给Java程序。

Java本地接口Java本地接口(JNI)是Java提供的一组用于实现Java与本地代码交互的API。

通过JNI,Java程序可以创建和操作本地对象、调用本地方法,并实现Java与本地代码之间的数据类型转换。

本地方法本地方法是用本地代码(通常是C或C++)实现的Java方法。

本地方法可以被Java程序调用,它可以处理一些特殊的本地操作,如访问硬件设备、调用操作系统接口等。

JNI实现原理JNI实现原理涉及到Java虚拟机(JVM)和本地代码之间的交互。

下面将详细介绍JNI的实现原理。

编写本地方法首先,我们在Java程序中定义一个本地方法。

本地方法使用native关键字修饰,表明该方法由本地代码实现。

生成包含本地方法声明的头文件然后,通过Java的javah命令生成包含本地方法声明的头文件。

头文件中声明了本地方法的名称、参数列表和返回类型。

实现本地方法接下来,我们使用C/C++编写本地代码,并实现Java程序中定义的本地方法。

在本地代码中,我们需要包含生成的头文件,以便让编译器知道本地方法的声明。

android native原理

android native原理

android native原理Android Native,也就是使用C/C++语言编写的Android应用程序,相对于Java/Kotlin等高级语言,具有更高的执行效率和更好的性能。

在Android系统中,Native应用程序通过使用Android NDK(Native Development Kit)来编译和运行C/C++代码。

NDK提供了一系列的工具和库,使得开发者可以使用C/C++语言编写Android应用程序的核心逻辑。

Android Native应用程序的原理包括以下几个方面:1. JNI(Java Native Interface)JNI是Java平台上的本地接口,它允许Java代码与其他语言编写的代码进行交互。

在Android Native应用程序中,JNI用于将Java代码和C/C++代码进行连接和通信。

JNI在Android应用程序中实现了一个Java虚拟机(JVM),这个虚拟机可以运行Java代码,同时也可以通过JNI调用C/C++代码。

2. Native ActivityNative Activity是Android系统提供的一个组件,它允许开发者使用C/C++代码实现Android应用程序的界面和逻辑。

Native Activity通过使用JNI来与Java 代码进行交互,从而实现与Android系统的集成。

3. Native ServiceNative Service是Android系统提供的一个服务组件,它允许开发者使用C/C++代码实现后台运行的服务。

Native Service可以与Java代码进行交互,同时也可以独立于Java应用程序运行。

4. Native LibraryNative Library是使用C/C++语言编写的一组函数库,它们可以被Java代码通过JNI调用。

在Android Native应用程序中,Native Library通常用于实现核心算法和性能敏感的代码。

java 不同系统之间传输数据的方法

java 不同系统之间传输数据的方法

java 不同系统之间传输数据的方法Java是一种强大且广泛应用的编程语言,用于开发各种类型的应用程序。

在实际开发中,经常需要在不同的系统之间传输数据。

本文将介绍一些常用的方法来实现Java不同系统之间的数据传输。

1. 使用Socket通信Socket通信是一种常用的网络通信方式,可以实现不同系统之间的数据传输。

通过Socket,我们可以在客户端和服务器之间建立一条双向通道进行数据交换。

在Java中,可以使用Java的原生Socket库来实现Socket通信。

客户端和服务器端通过准确的IP地址和端口号来建立连接。

客户端可以使用Socket类来与服务器进行通信,而服务器则使用ServerSocket类监听并接受客户端连接。

2. 使用HTTP协议HTTP协议是一种应用层协议,常用于Web应用程序中。

通过HTTP协议,不同系统之间可以通过发送和接收HTTP请求和响应来进行数据传输。

在Java中,可以使用Java的HttpURLConnection类或者第三方库,如Apache 的HttpClient来实现HTTP通信。

通过发送HTTP请求,可以将数据以请求参数或JSON/XML等格式发送到目标系统,并接收目标系统的HTTP响应。

3. 使用WebServiceWebService是一种通过网络进行通信的软件系统。

它可以使不同系统之间的应用程序通过Web服务接口进行数据传输和交互。

在Java中,可以使用Java的JAX-WS和JAX-RPC等API来开发和使用WebService。

通过定义WebService接口和实现相应的服务端和客户端,可以在不同系统之间轻松地传输数据。

4. 使用消息队列消息队列是一种常用的异步通信方式,允许不同系统之间以消息的形式传递数据。

消息队列将数据发送方发送的消息存储在队列中,接收方从队列中接收并处理消息。

在Java中,可以使用ActiveMQ、RabbitMQ等消息中间件来实现消息队列。

NDKJNI中Java和CC++互相传递数组

NDKJNI中Java和CC++互相传递数组

NDKJNI中Java和CC++互相传递数组NDK/JNI 中Java和C/C++互相传递数组Java 和 C/C++通过Jni这个中间件,可以实现相互之间的数组传递;我这⾥提供⼏种⽅式;供参考;第⼀种:Java通过JNI传递给C/C++,经过处理后,再复制到Java数组并返回;Java的本地⽅法定义:public native int[] arrEncode(int[] arr);C代码的实现:#include <jni.h>JNIEXPORT jintArray JNICALL Java_com_example_arrtoc_MainActivity_arrEncode(JNIEnv *env, jobject obj, jintArray javaArr){//获取Java数组长度int lenght = (*env)->GetArrayLength(env,javaArr);//根据Java数组创建C数组,也就是把Java数组转换成C数组// jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);int* arrp =(*env)->GetIntArrayElements(env,javaArr,0);//把数组元素值加10处理int i;for(i =0 ; i<lenght;i++){*(arrp+i) +=10;}//将C数组种的元素拷贝到Java数组中(*env)->SetIntArrayRegion(env,javaArr,0,lenght,arrp);return javaArr;}第⼆种⽅式:在C中直接操作元素,然后把C数组复制到Java数组中,并更新Java数组;Java声明的本地⽅法public native void arrEncode(int[] arr);C代码实现#include <jni.h>JNIEXPORT void JNICALL Java_com_example_arrtoc_MainActivity_arrEncode(JNIEnv *env, jobject obj, jintArray javaArr){//获取Java数组长度int lenght = (*env)->GetArrayLength(env,javaArr);//根据Java数组创建C数组,也就是把Java数组转换成C数组// jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);int* arrp =(*env)->GetIntArrayElements(env,javaArr,0);//把数组元素值加10处理int i;for(i =0 ; i<lenght;i++){*(arrp+i) +=10;}//将C数组种的元素拷贝到Java数组中(*env)->SetIntArrayRegion(env,javaArr,0,lenght,arrp);}第三种:在C代码中新建Java数组,然后把C中数组的元素复制到Java数组中在返回给Java;Java定义的本地⽅法:public native int[] arrEncode(int[] arr);C代码实现:#include <jni.h>JNIEXPORT jintArray JNICALL Java_com_example_arrtoc_MainActivity_arrEncode (JNIEnv *env, jobject obj, jintArray javaArr){//获取Java数组长度int lenght = (*env)->GetArrayLength(env,javaArr);//根据Java数组创建C数组,也就是把Java数组转换成C数组// jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);int* arrp =(*env)->GetIntArrayElements(env,javaArr,0);//新建⼀个Java数组jintArray newArr = (*env)->NewIntArray(env,lenght);//把数组元素值加10处理int i;for(i =0 ; i<lenght;i++){*(arrp+i) +=10;}//将C数组种的元素拷贝到Java数组中(*env)->SetIntArrayRegion(env,newArr,0,lenght,arrp);return newArr;}第四种:通过JNI种的ReleaseArrayElements⽅法实现:这个⽅法的最后⼀个参数是模式:。

jni 函数

jni 函数

jni 函数JNI 函数简介JNI(Java Native Interface)是一种允许Java代码调用和被C或C++代码调用的机制。

它提供了一种连接Java虚拟机(JVM)和本地代码的方式,使得Java程序可以调用底层的本地库,以及本地代码可以调用Java程序中的方法和对象。

在Android开发中,JNI函数起到了至关重要的作用。

它可以用于实现与底层硬件交互、调用第三方库、提高性能等。

本文将介绍一些常用的JNI函数及其用途。

1. JNIEnv 和 jclassJNIEnv是JNI的环境接口,它提供了一系列函数用于Java代码与本地代码之间的通信。

通过JNIEnv,我们可以获取Java虚拟机的实例,并调用Java方法、获取Java对象等。

jclass则代表Java中的类,在JNI中可以用来获取类的方法、字段等信息。

2. jstring 和 char*jstring是JNI中表示Java字符串的类型,它可以与C/C++中的char*进行互相转换。

通过JNIEnv的GetStringUTFChars函数可以将jstring转换为char*,而通过NewStringUTF函数可以将char*转换为jstring。

3. jint 和 intjint是JNI中表示Java整数的类型,它可以与C/C++中的int进行互相转换。

通过JNIEnv的GetIntField函数可以获取Java对象的整数字段值,而通过SetIntField函数可以设置Java对象的整数字段值。

4. jobjectArray 和 jobjectjobjectArray是JNI中表示Java对象数组的类型,它可以与C/C++中的数组进行互相转换。

通过JNIEnv的GetObjectArrayElement函数可以获取数组中的元素,而通过SetObjectArrayElement函数可以设置数组中的元素。

5. jmethodID 和 jfieldIDjmethodID和jfieldID是JNI中表示Java方法和字段的标识符。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

当你对数组的存取完成后,要确保调用相应的 ReleaseXXXArrayElements 函数,参数是对应 Java 数组和 GetXXXArrayElements 返回的指针。如果必要的话,这个释放函数会复制你做的任何变化(这样它们就反 射到 java 数组),然后释放所有相关的资源。
为了使用 java 对象的数组,你必须使用 GetObjectArrayElement 函数和 SetObjectArrayElement 函数,分 别去 get,set 数组的元素。GetArrayLength 函数会返回数组的长度。
/****************** 定义本地方法 ********************/ //输入常用的数值类型(Boolean,Byte,Char,Short,Int,Float,Double) public native void displayParms(String showText, int i, boolean bl);
描述 C/C++8 位整型 C/C++带符号的 8 位整型 C/C++无符号的 16 位整型 C/C++带符号的 16 位整型 C/C++带符号的 32 位整型 C/C++带符号的 64 位整型 e C/C++32 位浮点型 C/C++64 位浮点型 任何 Java 对象,或者没有对应 java 类型的对象 Class 对象 字符串对象 任何对象的数组 布尔型数组 比特型数组 字符型数组 短整型数组 整型数组 长整型数组 浮点型数组
//添加到 objcet 数组中 (env)->SetObjectArrayElement(args, i, _obj); } //返回 object 数组 return args;
}
全部的 C/C++方法实现代码如下: /* * * 一缕阳光(sundy)版权所有,保留所有权利。 */ /** * * TODO Jni 中一个从 Java 到 C/C++参数传递测试类 * * @author 刘正伟(sundy) * @see /sundy * @see mailto:sundy26@ * @version 1.0 * @since 2005-4-30 * * 修改记录:
在 C/C++中实现本地方法
生成 C/C++头文件之后,你就需要写头文件对应的本地方法。注意:所有的本地方法的第一个参数都是指 向 JNIEnv 结构的。这个结构是用来调用 JNI 函数的。第二个参数 jclass 的意义,要看方法是不是静态的 (static)或者实例(Instance)的。前者,jclass 代表一个类对象的引用,而后者是被调用的方法所属对 象的引用。
使用对象
JNI 提供的另外一个功能是在本地代码中使用 Java 对象。通过使用合适的 JNI 函数,你可以创建 Java 对 象,get、set 静态(static)和实例(instance)的域,调用静态(static)和实例(instance)函数。JNI 通过 ID 识别域和方法,一个域或方法的 ID 是任何处理域和方法的函数的必须参数。
为了存取 Java 简单类型的数组,你就要要使用 GetXXXArrayElements 函数(见表 B),XXX 代表了数组 的类型。这个函数把 Java 数组看成参数,返回一个指向对应的本地类型的数组的指针。
表B
函数 GetBooleanArrayElements GetByteArrayElements GetCharArrayElements GetShortArrayElements GetIntArrayElements GetLongArrayElements GetFloatArrayElements GetDoubleArrayElements JNI 数组存取函数
//给每一个实例的变量付值,并且将实例作为一个 object,添加到 objcet 数组中 for(int i=0; i < len; i++ ) {
//给每一个实例的变量付值 jstring jstr = WindowsTojstring(env,"我的磁盘名字是 D:"); //(env)->SetObjectField(_obj,str,(env)->NewStringUTF("my name is D:")); (env)->SetObjectField(_obj,str,jstr); (env)->SetShortField(_obj,ival,10);
//返回一个结构 public native DiskInfo getStruct();
//返回一个结构数组 public native DiskInfo[] getStructArray(); 编译生成 C/C++头文件
定义好了 Java 类之后,接下来就要写本地代码。本地方法符号提供一个满足约定的头文件,使用 Java 工 具 Javah 可以很容易地创建它而不用手动去创建。你对 Java 的 class 文件使用 javah 命令,就会为你生成 一个对应的 C/C++头文件。 1、在控制台下进入工作路径,本工程路径为:E:\work\java\workspace\JavaJni。 2 、 运 行 javah 命 令 : javah -classpath E:\work\java\workspace\JavaJni com.sundy.jnidemo ChangeMethodFromJni 本文生成的 C/C++头文件名为: com_sundy_jnidemo_ChangeMethodFromJni.h
//调用一个静态方法 public native int add(int a, int b);
//输入一个数组 public native void setArray(boolean[] blList);
//返回一个字符串数组 public native String[] getStringArray();
//新建 object 数组 args = (env)->NewObjectArray(len, objClass, 0);
/* 下面为获取到 Java 中对应的实例类中的变量*/
//获取 Java 中的实例类 jclass objectClass = (env)->FindClass("com/sundy/jnidemo/DiskInfo");
符号
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(参数类型)返回类型
返回值和参数类型根据等价约定映射到本地 C/C++类型,如表 JNI 类型映射所示。有些类型,在本地代码 中可直接使用,而其他类型只有通过 JNI 调用操作。
表A
Java 类型 boolean byte char short int long float double Object Class String Object[] boolean[] byte[] char[] short[] int[] long[] float[]
这些资料的例子中,大多数只是输入一些简单的参数,获取没有参数。而在实际的使用过程中,往往需要 对参数进行处理转换。才可以被 C/C++程序识别。比如我们在 C++中有一个结构(Struct)DiskInfo ,需要 传递一个类似于 DiskInfo *pDiskInfo 的参数,类似于在 C++这样参数如何传递到 Java 中呢?下面我们就 来讨论 C++到 Java 中方法的一些常见参数的转换:
※确定域和方法的符号
下面我们来看看,如果通过使用数组和对象,从 C++中的获取到 Java 中的 DiskInfo 类对象,并返回一个 DiskInfo 数组: //返回一个结构数组,返回一个硬盘信息的结构数组 JNIEXPORT jobjectArray JNICALL Java_com_sundy_jnidemo_ChangeMethodFromJni_getStructArray (JNIEnv *env, jobject _obj) {
表 C 列出了用以得到静态(static)和实例(instance)的域与方法的 JNI 函数。每个函数接受(作为参数) 域或方法的类,它们的名称,符号和它们对应返回的 jfieldID 或 jmethodID。
表C
函数 GetFieldID
描述 得到一个实例的域的 ID
GetStaticFieldID GetMethodID GetStaticMethodID ※域和方法的函数
得到一个静态的域的 ID 得到一个实例的方法的 ID 得到一个静态方法的 ID
如果你有了一个类的实例,它就可以通过方法 GetObjectClass 得到,或者如果你没有这个类的实例,可以 通过 FindClass 得到。符号是从域的类型或者方法的参数,返回值得到字符串,如表 D 所示。
表D
Java 类型
定义 Native Java 类:
如果你习惯了使用 JNI,你就不会觉得它难了。既然本地方法是由其他语言实现的,它们在 Java 中没有函 数体。但是,所有本地代码必须用本地关键词声明,成为 Java 类的成员。假设我们在 C++中有这么一个 结构,它用来描述硬盘信息:
相关文档
最新文档