2Java程序JNI調用C++之四步驟

javacode:TestNative.java

package com.cloud;
import java.util.Date;
public class TestNative {
	public static void main(String[] args) {
//		test1_TestModifyField();
//		test2_TestModifyField();
//		test3_TestModifyField();
		test4_TestCallMethod();
	}
	private static void test4_TestCallMethod() {
		System.loadLibrary("NativeTestCodeDLL");
		TestNative t = new TestNative();
		t.sayHello();
		
	}
	private static void test1_TestModifyField() {
		System.loadLibrary("NativeTestCodeDLL");
		TestNative t = new TestNative();
		t.sayHello();
	}
	private static void test2_TestModifyField() {
		System.loadLibrary("NativeTestCodeDLL");
		TestNative t = new TestNative();
		t.sayHello();
	}
	private static void test3_TestModifyField() {
		System.loadLibrary("NativeTestCodeDLL");
		TestNative t = new TestNative();
		t.sayHello();
		System.out.println("c++修改後:number值="+t.number);
	}
	/**
	 * 1、第一個例子(native)
	 * 被native修飾,表示該方法無需實現,調用本地的c/c++代碼
	 * 編寫java程序,方法必須用native修飾,並且方法不可以有實現體。
	 * 調用【native>本地的】c/c++程序
	 */
	public native void sayHello();
	
	/**
	 * 2、第二個例子
	 * c++中各種類的表示
	 */
	public int property = 10;
	public int function(int foo,Date date,int[] arr)
	{
		System.out.println("function");
		return 0;
	}
	public void showJava(int property)
	{
		System.out.println("This is showJava(int property);");
//		TestNative.property = property;
//		System.out.println("你好,Java"+property);
	}
	/**
	 * 3、第三個例子
	 * c++修改Java屬性。
	 */
	public int number = 10;
	
	/**
	 * 4、第四個例子
	 * c++呼叫Java方法
	 * @return
	 */
	public double max(double num1,double num2)
	{
		System.out.println("max()");
		return num1 > num2 ? num1 : num2;
	}
	
	
	
	
	
	
	
	
	
	
	
}


 

 

 

c++ code sourceTest.cpp

 

#include"com_cloud_TestNative.h"
#include<iostream>
using namespace std;
JNIEXPORT void JNICALL Java_com_cloud_TestNative_sayHello(JNIEnv * env, jobject obj)
{
	//第一個示例,用c++在控制檯輸出HelloWord。
	/*
	cout<<"Hello Word"<<endl;
	*/
	
	

	//第二個示例
	//反向c++調用Java

	/*
	jclass clazz_TestNative = env->GetObjectClass(obj);
	jfieldID fieldID_property = env->GetFieldID(clazz_TestNative,"property","I");
	cout<<fieldID_property<<endl;
	jmethodID jmethod_showJava = env->GetMethodID(clazz_TestNative,"showJava","(I)V");
	
	jmethodID jmethod_function = env->GetMethodID(clazz_TestNative,"function","(ILjava/util/Date;[I)I");
	*/

	//第三個例子
	//c++修改Java屬性
	/*
	jclass clazz_TestNative = env->GetObjectClass(obj);
	jfieldID id_number = env->GetFieldID(clazz_TestNative,"number","I");
	jint number = env->GetIntField(obj,id_number);
	cout<<number<<endl;
	env->SetIntField(obj,id_number,100L);
	*/

	//第四個例子
	//c++調用Java方法
	
	jclass clazz_TestNative = env->GetObjectClass(obj);
	jmethodID id_max = env->GetMethodID(clazz_TestNative,"max","(DD)D");
	jdouble maxReturnValue = env->CallDoubleMethod(obj,id_max,3.14,7.89);
	cout<<maxReturnValue<<endl;
	








}


 

 

 

編寫Java程序通過jni調用c、c++程序

1 編寫java程序,編寫一個 聲明調用c++的實現方法,方法必須用native修飾,並且方法不可以有實現體。
2 用jdk自帶的javah命令,運行cmd命令行切換到class文件的目錄下,或者指定classpath
3 在cmd命令行輸入【javah java文件全類名】生成class文件所對應的c++頭文件【.h文件】 。class目錄下生成了.h的文件代表生成頭文件成功。
4 用c++的ide VS2010 創建c++項目》Win32》Win32控制檯應用程序》,輸入項目名稱,下一步》選擇DLL>選擇 空的工程。然後生成項目。
5 把剛纔javah命令生成的頭文件【.h】文件複製到c++工程下面,然後在VS裏選中:頭文件》鼠標右鍵》添加》現有項,選擇複製過來的頭文件【.h】。
6 選中:源文件》添加》新建項》c++文件(.cpp)。輸入文件名,創建文件。
7 打開復制進來的頭文件,複製方法到創建的.cpp文件裏。
8 編寫c++代碼
示例如下:
#include"com_cloud_TestNative.h"
#include<iostream>
using namespace std;
JNIEXPORT void JNICALL Java_com_cloud_TestNative_sayHello(JNIEnv * env, jobject obj)
{
 cout<<"Hello Word"<<endl;
}

9 編譯。會發生錯誤。
第一個提示缺少jni.h文件,將jdk\include下面的jni.h文件拷貝到c++工程下,並且把<>括號修改爲雙引號,示例:#include "jni.h"
第二個提示缺少#include "jni_md.h",在jdk\include\win32裏找到jni_md.h,複製到c++工程下。
編譯通過。生成了c++項目的DLL文件。ok。
10 把dll動態鏈接庫路徑設置到環境變量Path中。
11 編寫Java程序調用DLL動態連接庫。java中用System.loadLibrary("TeatNative");DLL的文件名,不包含擴展名。加載TestNative.dll文件。
如果出錯,需要eclipse重啓,讓eclipse啓動的時候會重新加載環境變量
12 執行調用,輸出HelloWorld,成功!!!。

 

 

 

 

接下來,講解c++中調用Java程序
第三個參數簽名,通過javap -s -private/-p com.cloud.TestNative 命令生成。
1 靜態類對象獲取。
 首先要通過env->FindClass("com/cloud/TestNative");來獲得類對象,用jclass 類型來接收。
 例子:jclass clazz_TestNative = env->FindClass("com/cloud/TestNative");
 
  非靜態類對象獲取。 
   通過env->GetObjectClass(obj);來獲取類對象。ojb參數爲生成的頭文件方法的第二個參數。
   例子:jclass clazz_TestNative = env->GetObjectClass(obj);
   
2 方法對象獲取。
 c++中通過env->GetMethodID(clazz_TestNative,"showJava","(I)V");方法來獲得類方法的對象,用jmethodID類型來接收。
 例子:jmethodID id_func = env->GetMethodID(clazz_TestNative,"showJava","(I)V");
 
3 屬性對象獲取。
 通過evn->GetFieldID(clazz_TestNative,"property","I");
 例子:jfieldID fieldID_property = env->GetFieldID(clazz_TestNative,"property","I");
 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章