利用JNI访问C/VC程序

来源:互联网 发布:淘宝子账号权重值 编辑:程序博客网 时间:2024/06/18 09:20
        JAVA以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI。  
        JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。 
   
一、JAVA中所需要做的工作  
             在JAVA程序中,首先需要在类中声明所调用的库名称,如下:
            
static{  
      System.loadLibrary(“goodluck”);
}
   
 
   
             在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。    
             还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具体实现。如下:  
            
public   native   static   void   set(int   i);  
public   native   static   int   get(); 

            然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件。 
            例如程序TestDll.java,内容为:
public class TestDll {
    
static {
        System.loadLibrary(
"goodluck");
    }

    
    
public native static void set(int i);
    
    
public native static int get();
    
    
public static void main(String[] args){
        TestDll td 
= new TestDll();
        td.set(
10);
        System.out.println(td.get());
    }

}
 

        用javac  TestDll.java编译它,会生成TestDll.class。    
        再用javah   TestDll,则会在当前目录下生成TestDll.h文件,这个文件需要被C/C++程序调用来生成所需的        库文件。  
    二、C/C++中所需要做的工作  
        对于已生成的.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即            可。再把库文件拷贝到JAVA程序的路径下面,就可以用JAVA调用C/C++所实现的功能了。 
        接上例子我们先看一下TestDll.h文件的内容:
#define _Included_TestDll
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     TestDll
 * Method:    set
 * Signature: (I)V
 
*/

JNIEXPORT 
void JNICALL Java_TestDll_set
  (JNIEnv 
*, jclass, jint);

/*
 * Class:     TestDll
 * Method:    get
 * Signature: ()I
 
*/

JNIEXPORT jint JNICALL Java_TestDll_get
  (JNIEnv 
*, jclass);

#ifdef __cplusplus
}

#endif
#endif
        在具体实现的时候,我们只关心两个函数原型    
        JNIEXPORT   jint   JNICALL   Java_TestDll_get   (JNIEnv   *,   jclass);  
        和  
        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文件具体实现这两个函数:
      
#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运行它,就可以观察到结果了。
        备注:
        A  其中的jni.h通常在 jdk/include/ 可以先拷贝到VC安装目录下的include目录下.一劳永逸,以后可以方便使用        JNI技术.
        B  全部的数据类型需要考虑Java和VC的接口问题.用jint  jstring 等.
        C  函数名称和自动生成的.h文件中规定的一致.命名规则是: Java_使用类_方法名 
        6 全编译一下工程.
           如果没有出错,则此时生成动态链接库成功.
          把动态链接库拷贝到TestDll.java所在的目录上.


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 雪碧里气体太多瓶子涨得要炸怎么办 餐厅不清洗油烟管道物业该怎么办 用完权健洁净宝后奇痒的厉害怎么办 老房子铸铁暖气管从外锈蚀了怎么办 德意壁挂炉补水多了水压过高怎么办 新空调的散热片铜管漏了怎么办 猪舍被别人推掉漏电电到人怎么办? 网上买的燃气灶连接用软管怎么办 哈弗h3后减振器上支架坏了怎么办 汽车用收录机电机皮带断了怎么办 大便太粗把马桶堵了怎么办 大便过粗把马桶堵了怎么办 大便硬的像石头拉不出来怎么办 家里埋在地下的水管漏水怎么办 埋在墙里的水管漏水怎么办 开发商暗埋水管热熔接头漏水怎么办 钻墙把水管钻破了怎么办 钻墙时不小心把水管钻破了怎么办 孩子把同桌的铅笔盒弄坏了怎么办 水管伐坏了物业不给修怎么办 卫生间埋在地下的水管漏水怎么办 埋在地下的水管冻住了怎么办 洗脸盆下水管有眉笔掉堵了怎么办 楼上打空调眼导致墙面潮湿怎么办 阳台做防水了又贴砖还漏水怎么办 洗菜盆里的盖子吸住拔不起来怎么办 掉小区阴井盖里物业不管怎么办 卫生间下水道被头发堵了怎么办妙招 久量时尚夜光台灯不亮了怎么办 我想做水电暖工程没有资质怎么办 修手机被弄丢了没有开维修单怎么办 手机去维修被老板弄丢了怎么办 5年保修期过后房子楼顶漏水怎么办 墙内水管漏水怎么办3步骤巧维修 下面有地暖下面水管漏水怎么办 热水器接的塑料水管子漏水怎么办 电热水器烧热水时热水管漏水怎么办 户户通位置锁定模块异常1怎么办 户户通位置锁定模块异常3怎么办 逆战安全系统检测客户端异常怎么办 电视户户通位置信息模块异常怎么办