Java通过JNI调用C语言的方法

Java以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI。
Java通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使Java可以实现和本地机器的紧密联系,调用系统级的各接口方法。

简单介绍及应用如下:

一、Java中所需要做的工作

在Java程序中,首先需要在类中声明所调用的库名称,如下:

Java代码

static {        System.loadLibrary(“goodluck”);        }    static {   System.loadLibrary(“goodluck”);   } 在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。

还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具体实现。如下:

Java代码

public native static void set(int i);      public native static int get();     public native static void set(int i);   public native static int get();  然后编译该Java程序文件,生成CLASS,再用JavaH命令,JNI就会生成C/C++的头文件。

例如程序testdll.Java,内容为:

Java代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class testdll     
  {     
  static   
    {      
System.loadLibrary( "goodluck" );      
}      
public native static int get();     
public native static void set( int i);  
public static void main(String[] args)      
{     
  testdll test = new testdll();       
  test.set( 10 );      
  System.out.println(test.get());    
   }       
  }   
  public class testdll  
  {   static 
{   
System.loadLibrary( "goodluck" ); 
  }   
public native static int get();   
public native static void set( int i);  
  public static void main(String[] args)   
{   
testdll test = new testdll();  
  test.set( 10 );   
System.out.println(test.get());   
}   
}



用Javac testdll.Java编译它,会生成testdll.class。

再用Javah testdll,则会在当前目录下生成testdll.h文件,这个文件需要被C/C++程序调用来生成所需的库文件。

二、C/C++中所需要做的工作

对于已生成的.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即可。再把库文件拷贝到Java程序的路径下面,就可以用Java调用C/C++所实现的功能了。

接上例子。我们先看一下testdll.h文件的内容:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/* DO NOT EDIT THIS FILE - it is machine generated */      
#include          
/* Header for class testdll */          
#ifndef _Included_testdll          
#define _Included_testdll          
#ifdef __cplusplus         
  extern "C"
  {          
#endif          
/*       
  * Class: testdll        
* Method: get        
* Signature: ()I       
  */          
JNIEXPORT jint JNICALL Java_testdll_get          (JNIEnv *, jclass);         
  /*       
  * Class: testdll        
* Method: set        
* Signature: (I)V      
   */          
JNIEXPORT void JNICALL Java_testdll_set          (JNIEnv *, jclass, jint);         
  #ifdef __cplusplus          
}          
#endif         
  #endif     
/* DO NOT EDIT THIS FILE - it is machine generated */  
  #include   
  /* Header for class testdll */    
#ifndef _Included_testdll    
#define _Included_testdll    
#ifdef __cplusplus    extern "C" 
{    
#endif   
  /*    
* Class: testdll    
* Method: get    
* Signature: ()I    
*/    
JNIEXPORT jint JNICALL Java_testdll_get    (JNIEnv *, jclass);   
  /*    
* Class: testdll    
* Method: set    
* Signature: (I)V   
  */    
JNIEXPORT void JNICALL Java_testdll_set    (JNIEnv *, jclass, jint);   
  #ifdef __cplusplus    
}    
#endif    
#endif


Java代码

?
1
2
3
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);   
  
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);



和Java代码

?
1
2
3
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);   
  
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);



这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使Java的int类型与本地的int沟通的一种类型,我们可以视而不见,就当做int使用。函数的名称是Java_再加上Java程序的package路径再加函数名组成的。参数中,我们也只需要关心在Java程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。

好,下面我们用testdll.cpp文件具体实现这两个函数:

Java代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "testdll.h"       int i = 0 ;       
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)      
  {       
return i;       
}       
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)       
  {       
  i = j;       
  }   
  #include "testdll.h"   
int i = 0 ;   
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)  
  {  
  return i;  
  }   
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j) 
   {  
  i = j; 
   }

编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与Java中需要调用的一致,这里就是goodluck.dll

把goodluck.dll拷贝到testdll.class的目录下,Java testdll运行它,就可以观察到结果了。
http://developer.51cto.com  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值