使用JNI進(jìn)行Java與C/C++語言混合編程----在Java中調(diào)用C/C++生成的DLL動(dòng)態(tài)鏈接庫
JNI是Java Native Interface的英文縮寫,
中文翻譯為本地調(diào)用, 自從Java 1.1開始就成為了Java標(biāo)準(zhǔn)的一部分.
Java調(diào)用C/C++大概有這樣幾個(gè)步驟
編寫帶有native方法的Java類, 使用javac工具編譯Java類
使用javah來生成與native方法對(duì)應(yīng)的頭文件
實(shí)現(xiàn)相應(yīng)的頭文件, 并編譯為動(dòng)態(tài)鏈接庫(windows下是.dll, linux下是.so)
首先創(chuàng)建一個(gè)java工程,測(cè)試一下能不能調(diào)用openCV代碼:
public class hello { //很多教程會(huì)叫我們聲明成static,但是我用的時(shí)候報(bào)錯(cuò)了,所以我還是 //不聲明成static了 public native void sayHello(String path); public static void main(String[] args) { // TODO Auto-generated method stub hello h=new hello(); //有時(shí)候會(huì)報(bào)錯(cuò)說cannot load xxx.dll //只需要將生成的xxx.dll放到這 //條語句輸出的路徑下即可 System.out.println(System.getProperty("java.library.path")); //這里調(diào)用的是java本地庫,TestAgain不加.dll。 //怎樣生成.dll后面會(huì)介紹 System.loadLibrary("TestAgain"); h.sayHello("D:/images/5.jpg"); }
}
由于我用的是myeclipse編寫和編譯的Java程序,
只需要配置一下就可以用myeclipse生成xxx.h文件,
在myclipse->run->External Tools->External Tools configurations
一般需要選中一個(gè)工程才能run,然后就可以生成xxx.h頭文件了
working Directory:${project_loc}
arguments:-v -classpath "${project_loc}/src" -d "${project_loc}/jni"
${java_type_name}
制作.h文件還有一個(gè)更簡(jiǎn)單的辦法,那就是直接cmd到當(dāng)前工程的src目錄下,然后javah xxx(包名).xxx(類名),然后就可以了,舉例假設(shè)包名為com.action,類名為upLoad,而且src目錄下
則應(yīng)該是javah com.action.upLoad即可
這里我也有些地方?jīng)]搞懂,因?yàn)槲易约鹤鲞@個(gè)項(xiàng)目的時(shí)候,用過jdk 1.6 1.7 1.8,最后使用的jdk1.6+tomcat6.0開發(fā)的,但是當(dāng)我在location 中寫入jdk1.6 的bin/javah.exe,編譯我的javaweb工程時(shí)出現(xiàn)如下錯(cuò)誤:
??????????? com.servlet.HandleImg δ??? com.servlet.HandleImg ??????? javadoc: ???? - ??????? com.servlet.HandleImg?? [ Search Path: D:jdkjdkjrelib esources.jar;D:jdkjdkjrelib t.jar;D:jdkjdkjrelibsunrsasign.jar;D:jdkjdkjrelibjsse.jar;D:jdkjdkjrelibjce.jar;D:jdkjdkjrelibcharsets.jar;D:jdkjdkjrelibmodulesjdk.boot.jar;D:jdkjdkjreclassesD:MyEclipseProfessional2014workspaceHandleImage/src ] Error: δ??????????????κ?????????? -help??
因此我用的是我jdk1.7中bin/javah.exe生成的xxx.h頭文件,實(shí)在不行就只能下載兩個(gè)jdk了,知識(shí)水平有限,望有人能解決這個(gè)問題。
不管怎么說,最終頭文件是生成了,xxx.h文件在當(dāng)前工程jni文件夾下,如下圖:
打開后
然后就可以開始寫c++代碼了
file->new ->project 選擇visual C++ 和win32 Console Application然后ok
我的操作系統(tǒng)和myeclipse都是64位的,因此生成32位的dll,在myeclipse中調(diào)用,會(huì)出現(xiàn)錯(cuò)誤,這里就需要配一下
然后就是配置opencv環(huán)境,我用的是opencv2.4.4,具體的配置過程,去百度opencv2.4.4配置教程,這次是在debug|x64下添加propertySheet了,
繼續(xù)添加兩個(gè)路徑:C:Program FilesJavajdk1.7.0_80include和C:Program FilesJavajdk1.7.0_80includewin32,目的是為了引入三個(gè)頭文件jni.h和jni_md.h還有jawt_md.h
再就是右鍵工程 ->open folder in file explore 將上面生成的xxx.h文件copy到該文件夾下:
然后HeaderFile里面也放一份
第二種引入改頭文件的方法是直接新建一個(gè)頭文件Test.h(名字可以隨意取),然后將myEclipse中生成的頭文件的內(nèi)容全部復(fù)制到Test.h中,然后在引用的時(shí)候?qū)?include "com_Test_hello.h"改為#include "Test.h"即可
然后在source Files中新建TestAgain.cpp,代碼如下,
#include "com_Test_hello.h" #include#include #include #include #include using namespace std; using namespace cv; JNIEXPORT void JNICALL Java_com_Test_hello_sayHello (JNIEnv *env, jobject obj,jstring string){ const char* str = env->GetStringUTFChars(string, 0); char cap[128]; strcpy(cap, str); env->ReleaseStringUTFChars(string, 0); int len=strlen(cap); Mat imag, result; imag = imread(str,0); //將讀入的彩色圖像直接以灰度圖像讀入 //namedWindow("原圖", 1); // imshow("原圖", imag); result = imag.clone(); //進(jìn)行二值化處理,選擇30,200.0為閾值 threshold(imag, result, 30, 200.0, CV_THRESH_BINARY); //namedWindow("二值化圖像"); // imshow("二值化圖像", result); imwrite(str,result); printf("圖像二值化成功!"); }
然后就可以build->build solution
如何使用Debug生成的解決方案的話,上面的那些環(huán)境就應(yīng)該是在Debug下屬性表里面添加,而且生成的dll也是在Debug文件夾目錄下。
要是想用Release生成的話,同上步驟即可。
構(gòu)建成功后可以在這里找到
將.dll文件復(fù)制到之前Java代碼中System.out.println(System.getProperty("java.library.path"));這條語句輸出的路徑中任何一個(gè)文件夾下即可
最后回到myeclipse中運(yùn)行Java程序,就可以了
完成了這個(gè)調(diào)用后,就只需要將這個(gè)嵌入到j(luò)avaweb工程中即可
有些時(shí)候調(diào)用dll需要返回int數(shù)組,或者字符串,我再分享這兩個(gè)方法
返回一個(gè)int數(shù)組
生成的頭文件用javah生成.h頭文件
/* DO NOT EDIT THIS FILE - it is machine generated */ #include/* Header for class Test_floatArray */ #ifndef _Included_Test_floatArray #define _Included_Test_floatArray #ifdef __cplusplus extern "C" { #endif /* * Class: Test_floatArray * Method: haha * Signature: ()[I */ JNIEXPORT jintArray JNICALL Java_Test_floatArray_haha (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
#include "Test.h" #includeJNIEXPORT jintArray JNICALL Java_Test_floatArray_haha (JNIEnv *env, jobject obj){ //1.新建長(zhǎng)度len數(shù)組 jintArray jarr = env->NewIntArray(3); //2.獲取數(shù)組指針 jint *arr = env->GetIntArrayElements(jarr, NULL); //3.賦值 int i = 0; for (; i < 3; i++){ arr[i] = i; } //4.釋放資源 env->ReleaseIntArrayElements(jarr, arr, 0); //5.返回?cái)?shù)組 return jarr; }
返回一個(gè)字符串型數(shù)組,首先需要用一個(gè)stojstring()函數(shù),將c++的string類型轉(zhuǎn)換為const char 類型,再從const char 轉(zhuǎn)化為jstring類型,即可直接返回一個(gè)jstring類型
#include "test.h" #include#include using namespace std; jstring stoJstring(JNIEnv* env, const char* pat) { jclass strClass = env->FindClass("Ljava/lang/String;"); jmethodID ctorID = env->GetMethodID(strClass, " ", "([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); } JNIEXPORT jstring JNICALL Java_com_action_upLoadAction_shibie (JNIEnv *env, jobject obj, jstring path1, jstring path2, jstring path3){ const char* str1 = env->GetStringUTFChars(path1, 0); const char* str2 = env->GetStringUTFChars(path2, 0); const char* str3 = env->GetStringUTFChars(path3, 0); printf("%s ", str1); printf("%s ", str2); printf("%s ", str3); printf("你好 "); string str = "好#"; const char* chardata = str.c_str(); jstring jstr = stoJstring(env, chardata); return jstr; }
test.h文件內(nèi)容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include/* Header for class com_action_upLoadAction */ #ifndef _Included_com_action_upLoadAction #define _Included_com_action_upLoadAction #ifdef __cplusplus extern "C" { #endif /* * Class: com_action_upLoadAction * Method: Contrast * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT void JNICALL Java_com_action_upLoadAction_Contrast (JNIEnv , jobject , jstring , jstring, jstring); JNIEXPORT jstring JNICALL Java_com_action_upLoadAction_shibie (JNIEnv *, jobject, jstring, jstring, jstring); #ifdef __cplusplus } #endif #endif
關(guān)于java web,推薦去看我的另一篇文章:https://segmentfault.com/a/11...
然后關(guān)于有些方法需要返回某個(gè)參數(shù)如String,boolean等,可以參考這篇文章:
http://www.cnblogs.com/icejoy...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/70389.html
摘要:可惜收費(fèi)的,今天要介紹的完美驗(yàn)證碼識(shí)別系統(tǒng)是類似的免費(fèi)產(chǎn)品。調(diào)用函數(shù)相當(dāng)簡(jiǎn)單的,對(duì)比復(fù)雜的參數(shù),這個(gè)識(shí)別是相當(dāng)?shù)目旖荨? 此文已由作者徐迪授權(quán)網(wǎng)易云社區(qū)發(fā)布。 歡迎訪問網(wǎng)易云社區(qū),了解更多網(wǎng)易技術(shù)產(chǎn)品運(yùn)營(yíng)經(jīng)驗(yàn)。 講到驗(yàn)證碼識(shí)別,大家第一個(gè)可能想到tesseract。誠然,對(duì)于OCR而言,tesseract確實(shí)很強(qiáng)大,自帶的字模能識(shí)別絕大多數(shù)規(guī)整的中英文。但是驗(yàn)證碼畢竟不是OCR。對(duì)于現(xiàn)在...
摘要:這是坐標(biāo)百度,好像沒啥好研究的了,不過出于好奇還是想知道使用是如何做到把文字區(qū)域進(jìn)行框選的,所以接下來我們就看看如何在上使用實(shí)現(xiàn)圖片中的文字框選。一些探索 最近下了幾個(gè)OCR的App(比如白描),發(fā)現(xiàn)可以選中圖片中的文字行逐行轉(zhuǎn)成文字,覺得很有意思(當(dāng)然想用要花錢啦),想著自己研究一下實(shí)現(xiàn)原理,google之后,發(fā)現(xiàn)了兩個(gè)庫,一個(gè)是OpenCV,在機(jī)器視覺方面應(yīng)用廣泛,圖像分析必備利器。另一...
閱讀 852·2023-04-25 21:21
閱讀 3233·2021-11-24 09:39
閱讀 3075·2021-09-02 15:41
閱讀 2004·2021-08-26 14:13
閱讀 1835·2019-08-30 11:18
閱讀 2781·2019-08-29 16:25
閱讀 513·2019-08-28 18:27
閱讀 1587·2019-08-28 18:17