JNI学习--Java和C、C++之间的数据类型映射之string

原创 2012年03月29日 21:58:15

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

如在编译过程遇到问题,可参考http://blog.csdn.net/bjutstar/article/details/7383317

开发环境:

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

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 虚拟机中的数据结构。


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 <stdio.h>
#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 raises StringIndexOutOfBoundsException 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 <stdio.h>
#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部分。


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


JNI和C++中的String相互转换

JNI和C++中的String相互转换Uper目前仍在继续先前的工作,这两天一直在折腾jstring 和char* 之间是如何转换的。在网上找了些例子和张孝祥jni的视频,现把自己成功运行例子贴出来。...
  • uper945
  • uper945
  • 2007年12月14日 14:08
  • 15293

Android中JNI使用详解(4)---Java与C之间数据类型转换

Jni中基本类型转换对应的表格 Java类型 本地类型 说明 boolean jboolean 无符号,8位 byte jbyte 无符号,8位 ...

C/C++ 基本数据类型之间的相互转换 int / char / string / vector windows与linux通用

参考: http://blog.csdn.net/xinwang24/article/details/6612686 http://zhidao.baidu.com/link?url=or5e32M...

Android JNI学习笔记(四)-数据类型映射以及native调用java

1. 前言前几篇学习了jni开发的基本流程、动态注册native函数以及相关编译文件的编写,咱们也算是知道了jni开发,但是还不够,今天咱们来学习下,java和jni的数据类型映射(说白了就是对应关系...

java,c,c++ 语言之间基本数据类型的比较

转载自http://blog.csdn.net/wu928320442/article/details/5825170 当要进行底层移植的时候肯定会遇到这些问题。特整理了下。   java...

java,c,c++ 之间基本数据类型的比较和理解

在JAVA中一共有八种基本数据类型,他们分别是 byte、short、int、long、float、do le、char、boolean 整型 其中byte、short、int、long都是表示...

java,c,c++ 语言之间基本数据类型的比较

原文:http://blog.csdn.net/wu928320442/article/details/5825170 当要进行底层移植的时候肯定会遇到这些问题。特整理了下。 ...

《从零开始学Swift》学习笔记(Day 71)——Swift与C/C++混合编程之数据类型映射

原创文章,欢迎转载。转载请注明:关东升的博客  如果引入必要的头文件,在Objective-C语言中可以使用C数据类型。而在Swift语言中是不能直接使用C数据类型,苹果公司为Swift语言提供与C语...

JNI数据类型在C中的映射

1、一个JNI代码示例         首先,我们来看一个比较完整的
  • ljtyzhr
  • ljtyzhr
  • 2014年10月10日 14:31
  • 604

JNI、C/C++、java调用dll、java与c数据类型对应关系

JNI中java类型与C/C++类型对应关系 在如下情况下,需要在本地方法中应用java对象的引用,就会用到类型之间的转换:   1)java方法里面将参数传入本地方法; 2)在本地方法...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JNI学习--Java和C、C++之间的数据类型映射之string
举报原因:
原因补充:

(最多只允许输入30个字)