JNI处理是一个转化数据的过程,难点在于java与本地语言交流时的数据转化
2012-05-17 20:20
579 查看
本文通过两个例子来讲解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);
}
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);
}
相关文章推荐
- JAVA通过JNI调用本地C语言方法
- java处理http发送的数据转化为json格式并返回遇到的问题
- JAVA通过JNI调用本地C语言方法
- JAVA通过JNI调用本地C语言方法
- 关于使用java从http接口取数据保存到本地文件的中文乱码处理
- 一个java处理JSON格式数据的通用类(五)
- 一个java处理JSON格式数据的通用类
- JAVA通过JNI调用本地C语言方法
- java实现数据结构练习题--仅使用处理单个数字的I/O例程,编写一个过程以输出任意实数(可以是负的)
- java实现从一个数据库查询数据经过处理导入另外一个数据库中
- java处理大数据的一个优化解决方案
- 一个java处理JSON格式数据的通用类
- JAVA通过JNI调用本地C语言方法
- JNI学习笔记:(1)开篇(2)本地代码访问Java代码 (3)本地方法取得Java属性/调用java方法 (4)本地代码创建Java对象(包括javaString) (5) 本地方法处理java数组
- java 本地方法的实现过程 JNI
- 用java编写了一个计算器,阐述下编程过程遇到的难点?
- JNI学习笔记(四)JNI中本地语言创建Java对象并且访问具体方法(附例子)
- 一个java处理JSON格式数据的通用类(封装了一个class)
- 【Java】在跑数据过程异常的处理方法(异常后继续执行),个人觉得很有用
- 一个java处理JSON格式数据的通用类(封装了一个class)