JAVA使用JNI调用C/C++动态库

来源:互联网 发布:腾讯视频for mac官网 编辑:程序博客网 时间:2024/04/30 21:27

在实际使用中,我们经常会在JAVA和C/C++之间进行交互,比较通用的方法目前是使用JNI接口进行。

根据我在项目中使用的方法并结合icecreamchen的《JNI调用小结》,总结以下经验。

=====================================================

一.     什么是JNI?

JNIJava Native Interface的缩写。从Java1.1开始,JNI标准成为Java平台的一部分。通过JNI,可以实现Java和其他的语言代码的交互,常用的是JavaC/C++之间的交互。

二.     JNI的使用方法

这里以Helloworld.java调用HelloWorld.dll/HelloWorld.so为例,讲述JNI的使用方法。

1.      创建一个classHelloWorld.java),并声明一个native方法;

2.      使用javac编译该classHelloWorld.java),生成HelloWorld.class

3.      使用javah –jni生成C 头文件,其中包含native方法的原型。

4.      使用C/C++实现native方法(HelloWorld.c/ HelloWorld.cpp)。

5.      编译C代码(HelloWorld.c),创建动态库文件(HelloWorld.dll(for Windows)或者HelloWorld.so(for Linux));

6.      使用java类(HelloWorld.java),加载C动态库文件和native方法,实现二者交互。

下图是JNI的使用方法进行图例化解释:

JNI使用图例

 

1 JNI使用方法

三.     JNI应用实例

根据“二.JNI的使用方法”中介绍的步骤,我们做几个实例。

1.      简单的实例

1)      创建一个class,名称就用HelloWorld.java,并声明一个native方法;

public class HelloWorld {

    static {

        System.loadLibrary("HelloWorld");

    }

    private native void setMsg(String str);

   

    private native String getMsg();

 

    public static void main(String[] argv) {

        HelloWorld hw = new HelloWorld();

        hw.setMsg("HelloWorld");

        System.out.println(hw.getMsg());

    }

}

2)      执行javac HelloWorld.java命令,生成HelloWorld.class

3)      执行javah –jni HelloWorld命令,生成HelloWorld.h,其内容如下:

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

#include <jni.h>

/* Header for class HelloWorld */

 

#ifndef _Included_HelloWorld

#define _Included_HelloWorld

#ifdef __cplusplus

extern "C" {

#endif

/*

 * Class:     HelloWorld

 * Method:    setMsg

 * Signature: (Ljava/lang/String;)V

 */

JNIEXPORT void JNICALL Java_HelloWorld_setMsg

  (JNIEnv *, jobject, jstring);

 

/*

 * Class:     HelloWorld

 * Method:    getMsg

 * Signature: ()Ljava/lang/String;

 */

JNIEXPORT jstring JNICALL Java_HelloWorld_getMsg

  (JNIEnv *, jobject);

 

#ifdef __cplusplus

}

#endif

#endif

需要注意的是Java中的类型发生了变化,另外native方法前面增加了前缀。

4)      创建HelloWorld.cpp文件,在此我们使用VC++6.0做成HelloWorld.cpp

// HelloWorld.cpp : Defines the entry point for the DLL application.

//

 

#include "stdafx.h"

#include "HelloWorld.h"

char far* str;

 

JNIEXPORT void JNICALL Java_HelloWorld_setMsg

(JNIEnv *env, jobject obj, jstring jstr) {

              str = (char far*)env->GetStringUTFChars(jstr, NULL);

}

 

JNIEXPORT jstring JNICALL Java_HelloWorld_getMsg

(JNIEnv *env, jobject obj) {

              jstring jstr;

              jstr = env->NewStringUTF(str);

              return jstr;

}

5)      编译HelloWorld.cpp,生成HelloWorld.dll

6)      执行java HelloWorld命令,得到如下结果:

 

执行结果1 

2.      Package的实例

通常我们使用的source都是在某个Package中,这种情况下的处理稍有不同。还是以上面的示例为例,简单说明一下。

1)      创建一个class,名称就用HelloWorld.javaPackagejp.co.test,并声明一个native方法;

package jp.co.test;

 

public class HelloWorld {

    static {

        System.loadLibrary("HelloWorld");

    }

    private native void setMsg(String str);

   

    private native String getMsg();

 

    public static void main(String[] argv) {

        HelloWorld hw = new HelloWorld();

        hw.setMsg("HelloWorld");

        System.out.println(hw.getMsg());

    }

}

2)      jp/co/test/目录下使用javac HelloWorld.java命令,编译生成HelloWorld.class文件;

3)      此步稍有不同的是要在source Folder路径下执行javah jp.co.test.HelloWorld命令,执行成功后,也会在source Folder路径下生成jp_co_test_HelloWorld.h文件,其内容如下:

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

#include <jni.h>

/* Header for class jp_co_test_HelloWorld */

 

#ifndef _Included_jp_co_test_HelloWorld

#define _Included_jp_co_test_HelloWorld

#ifdef __cplusplus

extern "C" {

#endif

/*

 * Class:     jp_co_test_HelloWorld

 * Method:    setMsg

 * Signature: (Ljava/lang/String;)V

 */

JNIEXPORT void JNICALL Java_jp_co_test_HelloWorld_setMsg

  (JNIEnv *, jobject, jstring);

 

/*

 * Class:     jp_co_test_HelloWorld

 * Method:    getMsg

 * Signature: ()Ljava/lang/String;

 */

JNIEXPORT jstring JNICALL Java_jp_co_test_HelloWorld_getMsg

  (JNIEnv *, jobject);

 

#ifdef __cplusplus

}

#endif

#endif

 

4)      创建HelloWorld.cpp文件,native方法名要和jp_co_test_HelloWorld.h中的一致;

5)      编译HelloWorld.cpp,生成HelloWorld.dll

6)      HelloWorld.dll copysource Folder路径下,执行java jp.co.test.HelloWorld得到如下结果:

执行结果2

 

四.     结束语

至此,JNI的基本使用方法介绍完了,但在实际使用中可能还会存在各种各样的问题,如其他操作系统(如:Linux)下的使用方法,传递中文字符的问题,传递复杂类型的问题等等,这需要大家不断深入探讨和钻研,方可熟练运用。

 

=====================================================

以上难免有不妥甚至错误之处,敬请指正。

原创粉丝点击