1:vs2010創建新的動態鏈接庫 (DLL) 項目:
1.1:從“文件”菜單中,選擇“新建”,然後選擇“項目…”。
1.2:從“項目類型”窗格中選擇“Visual C++”下的“Win32”。
1.3:從“模板”窗格中,選擇“Win32 控制檯應用程序”。
1.4:爲項目起一個名稱
1.5:在“Win32 應用程序嚮導”對話框的“概述”頁中,按“下一步”
1.6:從“Win32 應用程序嚮導”中的“應用程序設置”頁中,選擇“應用程序類型”下的“DLL“
1.7:從“Win32 應用程序嚮導”的“應用程序設置”頁中,選擇“附加選項”下的“空項目”。
2:導入JNI庫,首先確定你裝好JDK
2.1:右鍵選擇你的項目-》屬性-》配置屬性-》c/c++(新建2個c++文件纔會顯示)-》常規,點擊附加包含目錄,編輯如圖:
2.1:添加2個路徑如圖:
3:開始java端程序打開eclipse:
3.1:我的代碼如下:
package com.myjava;
public class HelloWorld {
private native String print(String str);
private native int[] sumArray(int[] arr);
int a=1;
static int sa=2;
native void seta_sa();
//實例方法
void callStr(String str,int a[]){
System.out.println(str);
for(int i=0;i<a.length;i++)System.out.println(a[i]);
}
native void nativeCallStr();
//構造方法
native Hi gouzaoHi();
//修改成員數組
String myStr[]={"dd","aaa"};
public String[] getMyStr() {
return myStr;
}
public void setMyStr(String[] myStr) {
this.myStr =myStr;
}
public static void main(String[] args) {
HelloWorld hw=new HelloWorld();
//字符串
// String s=hw.print("yyy");
// System.out.println(s);
//數組
// int a[]={1,2,4};
// int sum[]=hw.sumArray(a);
// for(int i=0;i<sum.length;i++)
// System.out.println(sum[i]);
//成員變量
// hw.seta_sa();
// System.out.println("java a:"+hw.a);
// System.out.println("java sa:"+sa);
//成員方法
// hw.nativeCallStr();
//構造方法
// Hi hi=(Hi)hw.gouzaoHi();
// System.out.print(hi.hiStr);;
////修改成員數組
hw.nativeCallStr();
for(int i=0;i<hw.myStr.length;i++)
System.out.println("java:修改後 "+hw.myStr[i]);
}
static {//加載dll庫
System.loadLibrary("myJNITest");
}
}
下面爲第2個類:
package com.myjava;
public class Hi {
String hiStr="nihao hi";
Hi(String str){System.out.println("class Hi str:"+str);}
}
好的開始編譯生成class文件但會報錯沒關係只要生成class文件即可
4:開始-》運行,輸入cmd打開並定位到你java項目的bin文件夾下:
4.2:輸入命令javap -s -p -classpath 包名路徑 包名.文件名:
這樣你可以看到一堆與你java文件有關的對應JNI反編譯信息
4.3:生成頭文件輸入命令javah -classpath 包名路徑 包名.文件名:
你可以在你開始定位的java文件下看到.h文件:如我的在
5:現在在VS2010建一個.h文件一個.cpp文件,上步生成的.h文件內容對應此處生成的文件(讀者若有疑惑可以看看JNI一些基礎教程):
5.1:下面我的.h文件內容:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_myjava_HelloWorld */
#ifndef _Included_com_myjava_HelloWorld
#define _Included_com_myjava_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_myjava_HelloWorld
* Method: print
* Signature: ()V
*/
JNIEXPORT jstring JNICALL Java_com_myjava_HelloWorld_print
(JNIEnv *, jobject,jstring);
JNIEXPORT jintArray JNICALL Java_com_myjava_HelloWorld_sumArray
(JNIEnv *, jobject, jintArray);
JNIEXPORT void JNICALL Java_com_myjava_HelloWorld_seta_1sa
(JNIEnv *, jobject);
/*
* Class: com_myjava_HelloWorld
* Method: nativeCallStr
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_myjava_HelloWorld_nativeCallStr
(JNIEnv *, jobject);
JNIEXPORT jobject JNICALL Java_com_myjava_HelloWorld_gouzaoHi
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
5.2 .cpp文件內容:
#include <jni.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include "HelloWorld.h"
using namespace std;
JNIEXPORT jstring JNICALL Java_com_myjava_HelloWorld_print(JNIEnv *env, jobject obj,jstring prompt)
{
char buf[128];
const char *str;
//調用GetStringUTFChars,把1個Unicode字串轉成UTF-8格式字串,第2參數爲JNI_TRUE,將返回str的一個拷貝;爲
//JNI_FALSE將直接指向str的內容,當isCopy爲JNI_FALSE設爲NULL,不關心Java VM對返回的指針是否直接指向java.lang.String的內容
str = (env)->GetStringUTFChars(prompt, NULL);
if (str == NULL) {
return NULL;
}
scanf("%127s", buf);
printf("%s", str);
//調用ReleaseStringUTFChars釋放GetStringUTFChars中分配的內存
(env)->ReleaseStringUTFChars(prompt, str);
//使用JNIEnv->NewStringUTF構造java.lang.String;如果此時沒有足夠的內存,
//NewStringUTF將拋OutOfMemoryError異常,同時返回NULL
return (env)->NewStringUTF(buf);
}
//數組
JNIEXPORT jintArray JNICALL Java_com_myjava_HelloWorld_sumArray
(JNIEnv *env, jobject obj, jintArray arr){
jintArray jarr;
jint *carr;
jint i, sum = 0;
carr = env->GetIntArrayElements(arr, NULL);
if (carr == NULL) {
return 0; /* exception occurred */
}
for (i=0; i<env->GetArrayLength(arr); i++) {
sum += carr[i];
printf("%s,%d\n","c++的輸出",carr[i]);
}
//新建數組
int len=2;
int backArr[]={11,12};
jarr=env->NewIntArray(len);
env->SetIntArrayRegion(jarr,0,len,(jint*)backArr);
//釋放空間
env->ReleaseIntArrayElements(arr,carr,0);
env->ReleaseIntArrayElements(jarr,(jint*)backArr,0);
return jarr;
}
//修改成員變量
JNIEXPORT void JNICALL Java_com_myjava_HelloWorld_seta_1sa
(JNIEnv *env, jobject obj){
jfieldID fid;
jint ja,jsa;
jclass cls = env->GetObjectClass(obj);
//通過GetFieldID得到對象成員ID,第2參數對應屬性變量a,第3參數對應屬性a的jni簽名
fid = env->GetFieldID(cls, "a", "I");
ja=env->GetIntField(obj,fid);
cout<<"c++ ja:"<<ja<<endl;
env->SetIntField(obj,fid,ja+10);
//獲得靜態id
fid= env->GetStaticFieldID(cls, "sa", "I");
jsa=env->GetStaticIntField(cls,fid);
cout<<"C++ jsa:"<<jsa<<endl;
env->SetStaticIntField(cls,fid,jsa+10);
}
//調用成員方法
JNIEXPORT void JNICALL Java_com_myjava_HelloWorld_nativeCallStr
(JNIEnv *env, jobject obj){
jclass cls =env->GetObjectClass(obj);
//第2參數方法名,第3參數Ljava/lang/String;爲string簽名,[I爲數組簽名,V爲返回類型
jmethodID mid =env->GetMethodID(cls, "callStr", "(Ljava/lang/String;[I)V");
if (mid == NULL) {
return;
}
int len=2;
jint backArr[]={11,12};
jintArray jarr=env->NewIntArray(len);
env->SetIntArrayRegion(jarr,0,2,(jint*)backArr);
env->ReleaseIntArrayElements(jarr,backArr,0);
//第3個參數爲傳遞的值
env->CallVoidMethod(obj,mid,env->NewStringUTF("hello"),jarr);
//調用成員方法修改成員字符串數組,先獲得再修改
mid =env->GetMethodID(cls, "getMyStr", "()[Ljava/lang/String;");
jobjectArray msg=(jobjectArray)env->CallObjectMethod(obj, mid);
len =env->GetArrayLength(msg);
for(int i=0;i<len;i++){
jobject jo=env->GetObjectArrayElement(msg,i);
cout<<"C++:字符串數組修改前:"<<(env)->GetStringUTFChars((jstring)jo, NULL)<<endl;
}
string sa[] = { "Hello", "world!", "JNI", "is", "fun" };
mid =env->GetMethodID(cls, "setMyStr", "([Ljava/lang/String;)V");
jobjectArray args = (env)->NewObjectArray(sa->length(),(env)->FindClass("java/lang/String"),0);
for( int i=0; i <sa->length(); i++ ){
(env)->SetObjectArrayElement(args, i,(env)->NewStringUTF(sa[i].c_str()));
}
env->CallObjectMethod(obj, mid,args);
env->DeleteLocalRef(args);
}
//構造方法
JNIEXPORT jobject JNICALL Java_com_myjava_HelloWorld_gouzaoHi
(JNIEnv *env, jobject obj){
jclass hiClass;
jmethodID cid;
//類的路徑
hiClass =env->FindClass("com/myjava/Hi");
if(hiClass==NULL)return NULL;
//第2參數,構造方法爲<init>
cid =env->GetMethodID(hiClass, "<init>", "(Ljava/lang/String;)V");
if(cid==NULL)return NULL;
jobject jo=env->NewObject(hiClass,cid,env->NewStringUTF("gouzaoHi"));
env->DeleteLocalRef(hiClass);
return jo;
}
6:至此爲止所有準備做好,右鍵你的項目-》生成:ok你可以再你的c++項目debug文件下發現生成的.dll文件如:我的爲myJNITest.dll
7:拷貝他放入你的java項目如:
8:運行java文件即可(java文件有多個註釋,每個註釋對應不同的JNI調用方式讀者參考),若讀者想知道c++如何調用java可看下篇JNI(2)之c++調用java