关于JNI技术

来源:互联网 发布:罗技m720蓝牙连接mac 编辑:程序博客网 时间:2024/05/17 09:44
java Native interface: native关键字表示可以调用操作系统的底层函数.


  Java例子:Thread类的private native void start();


  主要内容:


  1、Java 通过JNI调用DLL,返回ArrayList.


  2、Jsp 通过JNI调用DLL.


  使用的开发工具:MyEclipse10.7 + java jdk1.6.0_35 + vs2010.


  一、Java层原型方法


  [java] view plaincopy


  package com.zdd.searcher;


  import java.util.ArrayList;


  public class SearchEngine {


  public native ArrayList<QueryResult> query(String imgFileName);


  static


  {


  System.loadLibrary("searchenginedll");


  }


  }


  [java] view plaincopy


  package com.zdd.searcher;


  /**


  * 查询结果项


  * @author zdd


  *


  */


  public class QueryResult


  {


  private String filePath; //


  private float similarity; //


  //构造函数


  public QueryResult() {


  filePath="";


  similarity = 0.0f;


  }


  public QueryResult(String filePath, float similarity) {


  this.filePath = filePath;


  this.similarity = similarity;


  }


  public String toString() {


  return "filePath: " + filePath + " similarity: " + similarity;


  }


  public String getFilePath() {


  return filePath;


  }


  public void setFilePath(String filePath) {


  this.filePath = filePath;


  }


  public float getSimilarity() {


  return similarity;


  }


  public void setSimilarity(float similarity) {


  this.similarity = similarity;


  }


  }


  二、生成.h文件


  [cpp] view plaincopy


  \src>javac com/zdd/searcher/SearchEngine.java


  \src>javah com.zdd.searcher.SearchEngine


  三、使用.h写dll项目


  使用vs新建win32 dll项目,将上述生成的com_zdd_searcher_SearchEngine.h文件导入项目。


  [cpp] view plaincopy


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


  #include <jni.h>


  /* Header for class com_zdd_searcher_SearchEngine */


  #ifndef _Included_com_zdd_searcher_SearchEngine


  #define _Included_com_zdd_searcher_SearchEngine


  #ifdef __cplusplus


  extern "C" {


  #endif


  /*


  * Class:     com_zdd_searcher_SearchEngine


  * Method:    query


  * Signature: (Ljava/lang/String;)Ljava/util/ArrayList;


  */


  JNIEXPORT jobject JNICALL Java_com_zdd_searcher_SearchEngine_query


  (JNIEnv *env, jobject _obj, jstring _imgFileName);


  #ifdef __cplusplus


  }


  #endif


  #endif


  若提示没有发现<jni.h>,则在VC++ Directories ->Include中添加JNI头文件:..\Java\jdk1.6.0_35\include和..\Java\jdk1.6.0_35\include\win32。


  四、将c++中的vector向量通过Native层以ArrayList集合对象的方式返回给Java.


  [cpp] view plaincopy


  SearchEngine *searcher = NULL;


  /*


  * Class:     com_zdd_searcher_SearchEngine


  * Method:    query


  * Signature: (Ljava/lang/String;)Ljava/util/ArrayList;


  */


  JNIEXPORT jobject JNICALL Java_com_zdd_searcher_SearchEngine_query


  (JNIEnv *env, jobject _obj, jstring _imgFileName)


  {


  if(searcher == NULL)


  searcher = new FaceImageSearch();


  //获取查询结果


  vector<QueryResult> results;


  searcher->query(jstringTostring(env, _imgFileName), results);


  jclass list_cls = env->FindClass("Ljava/util/ArrayList;");//获得ArrayList类引用


  if(list_cls == NULL)


  {


  std::cout << "list_cls is null \n" ;


  }


  jmethodID list_costruct = env->GetMethodID(list_cls , "<init>","()V"); //获得得构造函数Id


  jobject list_obj = env->NewObject(list_cls , list_costruct); //创建一个Arraylist集合对象


  //或得Arraylist类中的 add()方法ID,其方法原型为: boolean add(Object object) ;


  jmethodID list_add  = env->GetMethodID(list_cls,"add","(Ljava/lang/Object;)Z");


  jclass qr_cls = env->FindClass("Lcom/zdd/searcher/QueryResult;");//获得QueryResult类引用


  //获得该类型的构造函数  函数名为 <init> 返回类型必须为 void 即 V


  //第三个参数根据构造函数的类型设定


  //例如:"(Ljava/lang/String;F)V"表示Java中方法为void xxx(String, float)其中,xxx表示函数名


  //-------------------------------------------------


  //基本JNI域描述符


  //  Z   --  boolean


  //  B   --  byte


  //  C   --  char


  //  S   --  short


  //  I   --  int


  //  J   --  long


  //  F   --  Float


  //  D   --  double


  //引用类型的描述符


  //  Object  --  Ljava/lang/Object;   //注意此处的分号(;)是JNI的一部分,不能省。


  //  String  --  Ljava/lang/String;


  //  int[]   --  [I


  //  float[] --  [F


  //  String[] -- [Ljava/lang/String;


  //方法表示示例


  // int f (int i, Object object) -- (ILjava/lang/Object;)I


  //void set (byte[ ] bytes) --  ([B)V


  jmethodID qr_costruct = env->GetMethodID(qr_cls , "<init>", "(Ljava/lang/String;F)V");


  for(unsigned int i = 0; i < results.size(); i++)


  {


  //通过调用该对象的构造函数来new 一个 QueryResult实例


  jobject qr_obj = env->NewObject(qr_cls , qr_costruct, stringToJstring(env, results[i].imagePath.c_str()), results[i].similarity);  //构造一个对象


  env->CallBooleanMethod(list_obj , list_add , qr_obj); //执行Arraylist类实例的add方法,添加一个QueryResult对象


  }


  return list_obj;


  }


  五、char*和jstring相互传化


  [cpp] view plaincopy


  //jstring to char*


  char* jstringTostring(JNIEnv* env, jstring jstr)


  {


  char* rtn = NULL;


  jclass clsstring = env->FindClass("java/lang/String");


  jstring strencode = env->NewStringUTF("utf-8");


  jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");


  jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);


  jsize alen = env->GetArrayLength(barr);


  jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);


  if (alen > 0)


  {


  rtn = (char*)malloc(alen + 1);


  memcpy(rtn, ba, alen);


  rtn[alen] = 0;


  }


  env->ReleaseByteArrayElements(barr, ba, 0);


  return rtn;


  }


  //char* to jstring


  jstring stringToJstring(JNIEnv* env, const char* pat)


  {


  jclass strClass = env->FindClass("Ljava/lang/String;");


  jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");


  jbyteArray bytes = env->NewByteArray(strlen(pat));


  env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);


  jstring encoding = env->NewStringUTF("utf-8");


  return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);


  }


  其它代码略。


  六、编译dll,并将其放项目目录下(和src平行) 在java中使用如下代码测试


  [cpp] view plaincopy


  package com.zdd.searcher;


  import java.util.ArrayList;


  public class DllTest {


  /**


  * @param args


  */


  public static void main(String[] args) {


  // TODO Auto-generated method stub


  SearchEngine se = new SearchEngine();


  ArrayList<QueryResult> lists = se.query("");


  for(int i = 0; i < lists.size(); i++)


  {


  System.out.println(lists.get(i).getFilePath());


  }


  System.out.println("Done.");


  }


  }


  七、在JSP中使用JNI调用dll


  JSP本身分为bean的src目录和WebRoot的脚本目录,而我们的dll需要在src下的类中调用,于是遇到了将DLL和资源文件放置到什么地方的问题。并且使用MyEclipse自带的tomcat,不存在../tomcat/bin目录。


  最后解决方法:将DLL放置在..\Java\jdk1.6.0_35\bin下,可以访问。

如果想了解更多相关的资料请关注(深圳专业钻孔 www.sz-qiege.com)官网

0 0
原创粉丝点击