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