JNI(1)之java调用c++

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

项目地址:http://download.csdn.net/detail/qwezcl/5356079

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值