本文通过两个例子来讲解JNI的一个输入/输出应用。首先看一个String的输入输出的例子,下面是java部分的代码
public class Prompt {
private 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方法是调用c/c++等语言接口的方法,Static静态代码块加载dll文件,本例中dll文件的名称是Prompt.dll。
编译这个java类,得到class文件,用javah命令生成头文件(javah -jni Prompt),运行成功将获得一个Prompt.h文件,打开该文件可看到以下代码风之境地
:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Prompt */
#ifndef _Included_Prompt
#define _Included_Prompt
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Prompt
* Method: getLine
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_Prompt_getLine
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
以下是一个C语言编写的小代码
#include <jni.h>
#include <stdio.h>
#include "Prompt.h"
JNIEXPORT jstring JNICALL
Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)
{
char buf[128];
const char *str;
str = (*env)->GetStringUTFChars(env, prompt, NULL);
if (str == NULL) {
return NULL;
}
printf("%s", str);
(*env)->ReleaseStringUTFChars(env, prompt, str);
scanf("%s", buf);
return (*env)->NewStringUTF(env, buf);
}
用vc里的cl可生成dll文件。
本程序运行过程:
运行java程序,main方法内有三句:
Prompt p = new Prompt();
建立本类实例,这将执行静态块加载dll文件。
String input = p.getLine("Type a line: ");
执行本地方法,我认为这将到头文件Prompt.h中去找执行的方法,于是就找到了这句
JNIEXPORT jstring JNICALL Java_Prompt_getLine(JNIEnv *, jobject, jstring);
进而执行c语言中的方法
执行本方法最困惑的是“如何将java中本地方法的那个String类型的参数转化成C语言中要接收的参数,C语言返回的参数又要转化为java的String”。
在 jni.h(应该是在jdk中include文件架下的一个头文件)中定义了基本类型的转换(int - jint ,
float - jfloat
等),本地代码会调用jni的函数获取相应的内容,例如本例中的GetStringUTFChars函数,该函数将JString转化为了C语言中的
String,然后可以作为标准的C语言变量使用,处理后返回一个jString变量。
System.out.println("User typed: " + input);
打印结果。
下面看另外一个例子。
java代码:
public class InstanceFieldAccess {
private String s;
private native void accessField();
public static void main(String args[]) {
InstanceFieldAccess c = new InstanceFieldAccess();
c.setS("abc");
c.accessField();
System.out.println("In Java:");
System.out.println(" c.s = \"" + c.getS() + "\"");
}
static {
System.loadLibrary("InstanceFieldAccess");
}
public void setS(String s)
{
this.s = s;
}
public String getS()
{
return s;
)
}
以下是C语言代码:
#include <jni.h>
#include <stdio.h>
#include "InstanceFieldAccess.h"
JNIEXPORT void JNICALL
Java_InstanceFieldAccess_accessField(JNIEnv *env, jobject obj)
{
jfieldID fid; /* store the field ID */
jstring jstr;
const char *str;
//获取java类实例
jclass cls = (*env)->GetObjectClass(env, obj);
printf("In C:\n");
//获取java类实例的变量s
fid = (*env)->GetFieldID(env, cls, "s",
"Ljava/lang/String;");
if (fid == NULL) {
return; /* failed to find the field */
}
//获取变量s的值
jstr = (*env)->GetObjectField(env, obj, fid);
//将变量s的值转化为标准c语言能处理的类型
str = (*env)->GetStringUTFChars(env, jstr, 0);
if (str == NULL) {
return; /* out of memory */
}
printf(" c.s = \"%s\"\n", str);
//将str转化为jString 类型
(*env)->ReleaseStringUTFChars(env, jstr, str);
//修改jString 值为 “123”;
jstr = (*env)->NewStringUTF(env, "123");
(*env)->SetObjectField(env, obj, fid, jstr);
}
操作结果为:
In C:
c.s = "abc"
In Java:
c.s = "123"
从该例子来看,我认为,jni处理程序就是一个转化数据的过程,难点在于java与本地语言交流时的数据转化。
分享到:
相关推荐
#### 二、标准输入输出示例 - **cat命令**:此命令常用于展示文件内容。如果在命令行中未提供文件名,则cat会从标准输入读取数据并将其输出到标准输出。例如: ```bash $ cat Hello world Hello world Bye ...
这包括定义JNI函数接口,使用OpenSSL库(或者其他加密库)来实现AES算法,以及处理输入和输出数据。例如,我们可以定义一个JNI函数原型如下: ```c JNIEXPORT jbyteArray JNICALL Java_...
例如,使用`open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY)`打开串口,`cfsetispeed`和`cfsetospeed`设置输入和输出波特率。 5. **数据读写** 通过`read`和`write`函数实现串口数据的读取和发送。读取时需要...
MD5(Message-Digest Algorithm 5)是一种广泛使用的哈希函数,它可以将任意长度的输入转化为固定长度的输出,通常是一个128位的二进制数,通常以32位的十六进制字符串表示。MD5的主要用途是数据完整性校验,确保...
JNI在实现Java程序与本地系统调用之间的桥梁作用时,可以实现包括输入输出、图形处理、网络通信、线程操作等在内的多种功能。 在文档中提及的示例程序“ReadFile”,展示如何使用JNI从本地系统调用C函数,将文件...
4. **LED控制**:LED控制通常涉及到GPIO(通用输入/输出)接口。JNI代码需要设置GPIO引脚为输出模式,然后通过写入高电平或低电平来控制LED的亮灭。 在"LEDDemo"这个项目中,我们可以看到一个具体的示例,演示了...
在使用 JNI 调用 Java 方法时,需要正确地处理 C 和 C++ 的语法差异。 **解决方案**: 1. **C++ 与 C 的调用方式区别**:在 C++ 中,可以直接使用 `JNIEnv` 函数,而无需通过指针调用。但在 C 中,则必须使用 `...
- **输入输出函数**:如`printf`和`scanf`,用于标准输入输出操作,不同格式化字符串对应不同类型的数据。 - **指针**:表示内存地址的变量,`*`用于解引用,`&`获取变量的地址,指针常用于动态内存管理、数组操作...
在压缩包内的文件“20130922 JNI综合实验一:LED点亮+IO电平读取.doc”很可能是实验的详细指南,包含了步骤、代码示例和解释。文件名中的日期可能指示了实验的创建时间,即2013年9月22日。 总结来说,这个实验将...
2. **调用参数与返回值记录**:除了函数调用本身,模块还可能记录每个JNI函数调用的输入参数和返回值。这为分析函数行为提供了详细信息,例如,查看特定函数如何处理不同输入,或者检查是否有错误返回值。 3. **...
在Android应用中,你可以在Activity或Service中调用这个`convertImage`方法,传入输入图片路径和期望的输出路径。当方法执行时,JNI接口会触发C++代码的执行,从而完成图片转换。 为了使这个过程更顺畅,你还需要在...
- 生成头文件:使用`javah`命令,输入类名,生成`HelloWorld_jni.h`。 - C/C++实现:在`HelloWorld.cpp`中,实现`JNIEXPORT`开头的方法,调用`JNIEnv`指针和`jclass`参数,完成本地方法的逻辑。 - 配置构建:在...
2. **防止缓冲区溢出**:加密解密过程中,确保输入和输出大小被正确处理,避免内存安全问题。 3. **选择安全的加密库**:避免使用已知存在漏洞的加密算法,如DES,选择AES等更安全的替代方案。 4. **密钥管理**:...
这个LED灯示例提供了完整的源码,帮助开发者深入理解Android系统如何与硬件交互,并且支持GPIO(通用输入/输出)的扩展,适用于2440开发板,但可以进行移植以适应其他开发板。 1. 应用程序层(App): 在这一层,...
OpenSL ES是针对嵌入式设备优化的音频库,它提供了一套C语言接口,用于处理音频输入、输出、混音、效果处理等任务。在Android上,OpenSL ES可以替代AudioTrack和AudioRecord等API,提供更低的延迟和更高的性能。 2...
这通常涉及到在`build.gradle`文件中添加依赖项,并确保你的Android项目配置支持JNI和NDK,因为Mediapipe包含C++代码。 在`TestMediaPipe`这个示例中,可能包含了一些基本的手势识别流程图配置。流程图定义了如何...
这包括加载Torch Script模型,执行前向传播,以及处理输入和输出数据。 3. **Torch Script**:Torch Script是PyTorch的脚本语言,用于将Python代码转换为独立的、可执行的IR(Intermediate Representation)。这...
- 创建输入/输出流:`InputStream in = serialPort.getInputStream(); OutputStream out = serialPort.getOutputStream();` - 开始读写数据:使用`in.read()`读取数据,`out.write()`写入数据。 - 关闭串口:完成...
它提供了窗口管理、事件处理、音频输出、图像加载和渲染、以及键盘和鼠标输入等功能。SDL2的一个主要优点是它的跨平台性,可以在Windows、Linux、Mac OS X、Android和iOS等操作系统上运行。 **Android NDK和JNI** ...