浅谈JNI的使用-java调用动态链接库

来源:互联网 发布:淘宝的店铺号有什么用 编辑:程序博客网 时间:2024/05/16 12:55

      什么是JNI?Java Native Interface(Java本地接口)的简写。使用这个接口,可以轻松实现java对动态链接库(Dynamic Link Library(.dll/.so)文件的调用,以实现工程存在的一些C/C++的功能。本文主要结合vc++6.0与java编程。

 

一、建立java文件,文件名称为javacall.java
注意点:1、要对dll里面的方法做本地声明
          2、加载dll
示例代码:

public class javacall
{
    static
    {
        System.loadLibrary("jnidll"); // 注意:不写扩展名,名字要与dll的文件名一致.
    }
    public native static int add(int i, int j);
    public static void main(String[] args)
    {       
        javacall jc = new javacall();       
        int nRet = jc.add(2, 3);
        System.out.println(nRet);
    }
}

 

二、控制台编译
javac javacall.java           ------如果没有错,进行下一步
javah javacall                  ------生成javacall.h这个头文件

javacall.h文件如下:

 

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

#include <jni.h>
/* Header for class javacall */

#ifndef _Included_javacall
#define _Included_javacall
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     javacall
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_javacall_add
  (JNIEnv *, jclass, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

 

三、实现步骤一中声明的方法
     打开VC++6.0,建立空工程,工程名称为jnidll。把javacall.h放到该工程中导入。新建一个javacall.cpp源文件:

 

#include "javacall.h"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *)
{
    JNIEnv *env;
    vm->GetEnv((void**)&env, JNI_VERSION_1_2);
    /*jclass cls = env->FindClass("jnicli/DatabaseJNI");
    if (cls == NULL) {
        printf("Class jnicli/DatabaseJNI is not found/n");
    } else {
        env->RegisterNatives(cls, fastdbApiMethods, itemsof(fastdbApiMethods));   
    }*/
    return JNI_VERSION_1_2;
}

JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *)
{
    JNIEnv *env;
    vm->GetEnv((void**)&env, JNI_VERSION_1_2);
    /*jclass cls = env->FindClass("jnicli/DatabaseJNI");
    env->UnregisterNatives(cls);*/
}

JNIEXPORT jint JNICALL Java_javacall_add(JNIEnv *env, jclass cls, jint a, jint b)
{
    return (a + b);
}

 

 

 

 

四、编译和调试

      生成动态库jnidll.dll后,把该文件放入工作目录(F:/workspace/mytest)中,主要包含下列文件:

a、javacall.java;

b、javacall.class;

c、jnidll.dll

 

 

结果显示:

5

 

说明
1)在JAVA程序中,首先需要在类中声明所调用的库名称System.loadLibrary(String libname),在库的搜寻路径中定位这个库。定位库的具体操作依赖于操作系统。在windows下,首先从当前目录查找,然后再搜寻PATH环境变量列出的目录.如果找不到该库,则会抛出UnsatisfiedLinkError.
2)这里加载的是JNI生成的dll,而不是其他生成的dll的名称.在这里库的扩展名字可以不用写出来,究竟是.dll还是.so由系统自己判断.
3)还需要对将要调用的方法做本地声明,关键字为native.并且只需要声明,而不需要具体实现.
4)如果加了static表明是静态方法,如果不加表明是一般的方法.加与不加生成的头文件中有一个参数不同.

解释:
1)加了static和不加只是一个参数的区别吗,就是jclass的不同,不加static这里就是jobject.
2)这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的.而jstring是以JNI为中介使JAVA的String类型与本地的string沟通的一种类型,我们可以视而不见,就当做String使用(具体对应见表一).函数的名称是JAVA_再加上java程序的package路径再加函数名组成的(参见有包的情况).参数中我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*和jclass我们可以通过深入研究隐式调用它.

 

CJava编程语言之间传送值时,需要理解这些值类型在这两种语言间的对应关系。这些都在头文件jni.h中,用typedef语句声明了这些类在目标平台上的代价类。头文件也定义了常量如:JNI_FALSE=0JNI_TRUE=1;表一说明了Java类型和C类型之间的对应关系。

 

表一   Java类型和C类型

 

Java编程语言

C编程语言

字节

boolean

jboolean

1

byte

jbyte

1

char

jchar

2

short

jshort

2

int

jint

4

long

jlong

8

float

jfloat

4

double

jdouble

8

原创粉丝点击