ANDROID JNI中C和JAVA的参数如何传递
- 格式:pdf
- 大小:168.97 KB
- 文档页数:11
首先要强调的是,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指令的使用以及图解教材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(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实现原理介绍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,也就是使用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不同系统之间的数据传输。
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++互相传递数组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(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. 传值(Call by Value):参数按照值的方式进行传递,函数接收的是实际参数的一个副本。
在函数内部对参数的修改不会影响到原始的参数。
这是最常见的参数传递方式,在许多编程语言中都是默认的方式。
特点:-参数的值在函数内部是只读的,函数不会对原始的参数进行修改。
-通过副本传递参数,避免了对原始参数进行意外修改的风险。
优点:-参数的值是独立于函数之外的,可以保证函数的安全性和一致性。
-函数内部对参数的修改不会影响到原始的参数,避免了意外的副作用。
缺点:-对于较大的数据类型,由于需要复制参数的值,会消耗更多的内存和时间。
2. 传引用(Call by Reference):参数按引用的方式进行传递,函数接收的是实际参数的引用或指针。
在函数内部对参数的修改会影响到原始的参数。
在引用传递参数的语言中,使用引用的方式可以让函数修改原始参数的值。
特点:-参数在函数内部是可写的,可以对参数进行修改。
-函数通过引用访问参数,可以直接修改原始参数的值。
优点:-函数可以直接修改原始参数的值,方便了对参数的修改操作。
-不需要复制参数的值,减少了内存和时间的消耗。
缺点:-参数的值可以被函数随时修改,可能导致意外的副作用,使程序变得难以理解和调试。
-对于没有被传引用的参数,无法从函数内部访问到其值。
3. 传地址(Call by Address):参数按照地址的方式进行传递,函数接收的是实际参数的地址。
在函数内部对参数进行修改会影响到原始的参数。
传地址方式类似于传引用,不同之处在于传地址是通过参数的指针来修改参数的值。
特点:-参数在函数内部是可写的,可以对参数进行修改。
-函数使用指针访问参数,可以直接修改原始参数的值。
优点:-函数可以直接修改原始参数的值,方便了对参数的修改操作。
Androidjnindk编程⼆:jni数据类型转换(primitive,String,a。
⼀.数据类型映射概述从我们开始jni编程起,就不可能避开函数的参数与返回值的问题。
java语⾔的数据类型和c/c++有很多不同的地⽅,所以我们必须考虑当在java层调⽤c/c++函数时,怎么正确的把java的参数传给c/c++函数,怎么正确的从c/c++函数获取正确的函数返回值;反之,当我们在c/c++中使⽤java的⽅法或属性时,如何确保数据类型能正确的在java和c/c++之间转换。
回顾我们上⼀篇⽂章中的那个c函数:#include <stdio.h>#include <jni.h>#include <stdlib.h>JNIEXPORT jstring JNICALL Java_com_jinwei_jnitesthello_MainActivity_sayHello(JNIEnv * env, jobject obj){return (*env)->NewStringUTF(env,"jni say hello to you");}这个函数⾮常简单,它没有接受参数,但是它返回了⼀个字符串给java层。
我们不能简单的使⽤return “jni say hello to you”;⽽是使⽤了NewStringUTF函数做了个转换,这就是数据类型的映射。
普通的jni函数⼀般都会有两个参数:JNIEnv * env, jobject obj,第三个参数起才是该函数要接受的参数,所以这⾥说它没有接受参数。
1.1JNIEnv * envJNIEnv是⼀个线程相关的结构体, 该结构体代表了 Java 在本线程的运⾏环境。
这意味不同的线程各⾃拥有各⼀个JNIEnv结构体,且彼此之间互相独⽴,互不⼲扰。
NIEnv结构包括了JNI函数表,这个函数表中存放了⼤量的函数指针,每⼀个函数指针⼜指向了具体的函数实现,⽐如,例⼦中的NewStringUTF函数就是这个函数表中的⼀员。