首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

JNI技术总结

2013-03-13 
JNI技术小结主要内容:1、Java 通过JNI调用DLL,返回ArrayList.2、Jsp 通过JNI调用DLL. 使用的开发工具:MyEcli

JNI技术小结

主要内容:

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

2、Jsp 通过JNI调用DLL.

 

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

 

一、Java层原型方法

 

package com.zdd.searcher;import java.util.ArrayList;public class SearchEngine {public native ArrayList<QueryResult> query(String imgFileName);static{System.loadLibrary("searchenginedll");}}

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文件

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


三、使用.h写dll项目

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

/* 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 __cplusplusextern "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.

 

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相互传化

//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 jstringjstring 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中使用如下代码测试

package com.zdd.searcher;import java.util.ArrayList;public class DllTest {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubSearchEngine 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下,可以访问。


 

 

热点排行