c type 对应java_JNI学习–Java和C、C++之间的数据类型映射之string | 学步园

本文主要的内容来源于Java

Native Interface: Programmer's Guide and Specification中的第三章的内容。可通过http://java.sun.com/docs/books/jni/下载该书。

开发环境:

Win7+VS2010+JDK1.6.0_27

1、声明本地方法

新建文件Prompt.java,输入以下内容

class Prompt {

// native method that prints a prompt and reads a line

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");

}

main函数通过调用native method getLine来接收用户输入的字符串

2、编译为class文件

javac Prompt.java

3、生成本地方法的头文件

javah -jni Prompt

头文件Prompt.h内容为

/* DO NOT EDIT THIS FILE - it is machine generated */

#include

/* 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

The name of the C function is formed by concatenating the “Java_” prefix, the class name, and the method name.

C函数的名字由前缀Java、类名、方法名连接而成。

The first parameter, the JNIEnv interface

pointer, points to a location that contains a pointer to a function table. Each entry

in the function table points to a JNI function. Native methods always access data

structures in the Java virtual machine through one of the JNI functions.

参数JNIEnv指向一个包含函数表的指针,函数表的指针的每一个入口指向一个JNI函数。native methods通过JNI函数访问Java 虚拟机中的数据结构。

1333029787_6653.png

The second argument differs depending on whether the native method is a

static or an instance method. The second argument to an instance native method is

a reference to the object on which the method is invoked, similar to the this

pointer in C++. The second argument to a static native method is a reference to

the class in which the method is defined. Our example, Java_Prompt_getLine,

implements an instance native method. Thus the jobject parameter is a reference

to the object itself.

第二个参数的作用因该native method是static或instance method而不同。对于instance native method,和C++中的this指针类似。对于static native method,它是这个类中定义的方法的一个引用。在我们的例子中,jobject对应object本身。

4、实现本地方法(本文最后将对各种实现方法进行一个简单的介绍)

Java_Prompt_getLine函数接收到prompt传过来的一个jstring类型的参数。jstring代表Java虚拟机中的字符串,和C中的字符指针(char*)是不同的。

你的native method code必须使用合适的JNI函数把jstring对象转换为C/C++类型的字符串。JNI支持Unicode和UTF-8之间的字符串的转换。

Unicode代表的字符是16位的,而UTF-8的编码方案向上兼容7位的ASCII。UTF_8 strings的作用类似NULL-terminated C strings。

新建Prompt.c文件,编写如下内容,推荐使用第二种方法。

第一种实现方法

GetStringUTFChars把jstring转换为UTF-8的格式,在确保原始的字符都是7位的ASCII字符时,可以把转换后的字符串传递给一般的C语言的库函数,比如printf,对于非ASCII字符我可能会在以后讨论,后者参考书中的8.2。

不要忘记检查返回值。因为Java虚拟机的实现需要分配空间给UTF_8字符串,因此,有可能内存分配失败。分配失败时,返回NULL,并且抛出OutOfMemoryError异常。此处,需要显示的返回语句来跳过C函数中后面的语句,因为A pending exception thrown through the JNI does not automatically change control flow in native C code

(native C code的控制流不一定因为异常而自动改变)

当不使用UTF-8字符串时,需要释放。

可以通过在native method中调用JNI function NewStringUTF来构造一个新的java.lang.String实例。

#include

#include "Prompt.h"

JNIEXPORT jstring JNICALL

Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)

{

char buf[128];

const jbyte *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);

}

第二种实现方法

The GetStringUTFRegion function takes a starting index and length, both

counted as number of Unicode characters. The function also performs bounds

checking, and raisesStringIndexOutOfBoundsException if necessary. In the

above code, we obtained the length from the string reference itself, and are thus

certain that there will be no index overflow. (The above code, however, lacks the

necessary checks to ensure that the prompt string contains less than 128 characters.)

The code is somewhat simpler than using GetStringUTFChars. Because Get-

StringUTFRegion performs no memory allocation, we need not check for possible

out-of-memory conditions. (Again, the above code lacks the necessary checks

to ensure that the user input contains less than 128 characters.)

比使用GetStringUTFChars的代码在某种程度上要简洁,因为GetStringUTFRegion的执行不需要内存分配,我们不需要检查可能的内存溢出情况。

#include

#include "Prompt.h"

JNIEXPORT jstring JNICALL

Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)

{

char outbuf[128], inbuf[128];

int len = (*env)->GetStringLength(env, prompt);

(*env)->GetStringUTFRegion(env, prompt, 0, len, outbuf);

printf("%s", outbuf);

scanf("%s", inbuf);

return (*env)->NewStringUTF(env, inbuf);

}

当然,还有其他的函数,比如GetStringCritical,如果使用不当可能出现死锁,如果想学习的话,可以参考书中的3.2部分。

1333029658_2382.png

5、编译C的源码,生成本地库

cl -Ic:\java\include -Ic:\java\include\win32 -MD -LD Prompt.c -FePrompt.dll

6、运行程序

java Prompt

结果如下

Type a line: heihei

User typed: heihei

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值