Java採用JNI調用VC++生成的dll(Java與C++交互)


     應項目需求,須要android調用java,java再調用C++實現android一個圖片匹配的功能,我們作為java組須要和C++和Android進行交互。以下是java和C++採用JNI的方式進行接口傳參交互,我做的一個demo並執行成功。

     什么是JNI?

     JNI全拼是Java Native Interface,中文意思為Java本地調用。JNI標准是Java平台的一部分。它同意java和其它語言的代碼進行交互。JNI開始是為了本地已經編譯好的語言,尤其是C和C++而設計的。我們也能夠使用JNI和其它語言進行溝通。我們僅僅要調用約定受支持了就能夠了。

     什么原理?

     我們知道C++中或者C#等.net都能生成.dll類庫。而C++(或.net)中生成的.dll文件,相當於我們java程序中java源碼通過編譯生成的.class文件。我們在java程序中直接通過code調用C++的dll文件就可以。

     在C語言中假設生成一個動態鏈接庫dll文件的時候。須要兩部分,一部分是為.h的頭文件,這個文件是負責對一些方法的聲明,而.cpp文件負責對方法的實現。

而在java中,在安裝JDK文件夾的include包中有個jni.h和jni_md.h,這個能夠說是java公布的一個接口,在C++中能夠直接使用這兩個head類型的文件對java要調用的C++方法編譯。讓java調用,並能夠接收java傳遞過來的參數。直接上代碼啦。


     詳細的過程例如以下所看到的(java公布一個接口,讓C++實現乘法的功能)

     1、建立java源碼例如以下所看到的。

     建立java project,在src下建立com包,在com包以下建立我們的java類Reliability.java,代碼例如以下所看到的。

package com;
public class Reliability {
	static {
		try {
			System.loadLibrary("Reliability"); // call dll
		} catch (UnsatisfiedLinkError e) {
			System.out.println("The load problem");
		}

	}
	public native int shanfei(int i);
	public static void main(String[] args) {
		Reliability reliability = new Reliability();
		System.out.print(reliability.shanfei(6));
	}
}

     2、編譯.java源文件。

     我們想實現傳遞int 整型參數來實現自己和自己相乘的結果,而實現shanfei(int p)方法的是C++。我們能夠通過System.loadLibrary("Reliability")方法實現載入C++生成的dll,通過native聲明方法接口以及參數。     

     編寫好自己的Reliability.java代碼后,能夠使用MyEclipse編譯為Reliability.class文件或者是直接用javac命令編譯為.class文件。

     我的使用的MyEclipse進行編譯的,會在/Reliability/bin/com目錄中生成Reliability.class文件。


     3、用javah 命令讓Reliability.class文件生成C++須要的.h文件。也就是交給C++的接口。

     在這里須要注意的是,一定要轉到你編譯成class文件的上一級文件夾進行javah命令,而且你的JDK已經配置好環境變量。這里的環境變量為JAVA_HOME:安裝jdk bin文件夾的上一級文件夾,比方我的jdk安裝在C:\java\bin....,那我的JAVA_HOME為:C:\java 。path文件夾:引用JAVA_HOME而且加上\bin ,為 %JAVA_HOME%\bin

classpath為: .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;這是一定要配置好的。

然后在dos窗體例如以下編寫例如以下命令。生成給C++ .h的文件。



     這樣在你的class文件上一級文件夾中就會出現.h 的文件。而且引入到你的MyEclipse中,與com包同級。


     4、這樣java已經給C++公布好了com_Reliability.h的頭文件。C++要去實現這種方法了。

     由於要生成dll文件,所以我們須要建立動態鏈接庫文件。假設用的是C++ 6.0環境,就是建立projects --Dynamic-LInk Library工程。

之后加入我們的com_Reliability.h文件到我們的DLL項目中,文件夾結構例如以下所看到的。


     頭文件里的代碼例如以下所看到的。com_Reliability.h。

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_Reliability */

#ifndef _Included_com_Reliability
#define _Included_com_Reliability
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_Reliability
 * Method:    shanfei
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_com_Reliability_shanfei
  (JNIEnv *, jclass, jint);

#ifdef __cplusplus
}
#endif
#endif

      實現的Reliability.cpp代碼例如以下所看到的。

#include<jni.h>
#include "com_Reliability.h"
#include<stdio.h>
#include<jni_md.h>

JNIEXPORT jint JNICALL Java_com_Reliability_shanfei(JNIEnv *, jclass, jint p)
{
	 int j = p*p;
	 return j;
		
}

     切忌:.cpp中和.h中的方法名一定要同樣!!

而且把從java中找到的jni.h 和jni_md.h粘貼到外部依賴目錄。或者直接放到VC98\include目錄中。


     5、生成dll文件

     這樣我們ctrl+F7編譯,F7在C++項目的debug中生成Reliability.dll文件,這樣我們再把這個dll文件放到java編譯的.class文件夾。同一時候放到MyEclipse與src同級。這樣執行java的Reliability.java文件。就看到C++給我們計算的結果了。顯演示樣例如以下所看到的。



     總結:

     上述大致就是這個過程,在這個過程中會出現這樣或者那樣的問題,我也在不斷的去嘗試錯誤的所在,嘗試修改,最根本的就是計算機報錯了。就一定是自己哪個地方有錯誤,抱着這種心態,耐心的找答案、嘗試、思考,設置斷點調試,看究竟是哪步出現的錯誤,終於會解決這個問題,讓你興奮的看到執行結果。






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM