Chinaunix首页 | 论坛 | 博客
  • 博客访问: 116750
  • 博文数量: 83
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 50
  • 用 户 组: 普通用户
  • 注册时间: 2013-10-31 11:07
个人简介

弃我去者,昨日之日不可留; 乱我心者,今日之日多烦忧。

文章分类

分类: Java

2014-11-13 16:19:39

C程序控制Java端代码
整个示例程序有 JniFuncMain类(包含本地方法声明)、JniTest对象和jnifunc.dll(包含本地方法的具体实现)三部分组成。在JniFuncMain类的本地方法中调用JniTest对象的方法和成员变量,具体由C++代码实现,包含在jnifunc.dll中。

1、 
编写Java代码 JniFuncMain.java和JniTest.java
JniFuncMain.java

点击(此处)折叠或打开

  1. public class JniFuncMain
  2. {
  3.     private static int staticIntField = 300;
  4.     
  5.     //加载本地库jnifunc.dll
  6.     static { System.loadLibrary("jnifunc");}

  7.     //本地方法声明
  8.     public static native JniTest createJniObject();

  9.     public static void main(String[] args)
  10.     {
  11.         //从本地代码生成JniTest对象
  12.         System.out.println("[Java] createJniObject()调用本地方法");
  13.         try{
  14.             JniTest jniObj = createJniObject();
  15.             
  16.             //调用JNiTest对象的方法
  17.          jniObj.callTest();
  18.                 }catch(Exception e)
  19.                 {
  20.                     System.out.println(e.getMessage());
  21.                 }
  22.         
  23.     }
  24. }
JniTest.java

点击(此处)折叠或打开

  1. class JniTest
  2. {
  3.     private int intField;
  4.     
  5.     //构造方法
  6.         public JniTest(int num)
  7.         {
  8.             intField = num;
  9.             System.out.println("[Java}调用JniTest对象的构造方法:intField = " + intField);
  10.         }
  11.     //此方法由JNI本地函数调用
  12.     public int callByNative(int num)
  13.     {
  14.         System.out.println("[Java] JniTest对象的callByNative(" + num + ")调用");
  15.         return num;
  16.     }


  17.     public void callTest()
  18.     {
  19.         System.out.println("[Java] JniTest对象的callTest方法调用:intField = " + intField);
  20.     }
  21. }

 2、  编译Java代码

D:\Users\lusi\JNI\JNI-2>  Javac  JniFuncMain.java

3、  生成C语言需要包含的头文件JniFuncMain.h

D:\Users\lusi\JNI\JNI-2>  Javah  JniFuncMain

JniFuncMain.h

点击(此处)折叠或打开

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

  4. #ifndef _Included_JniFuncMain
  5. #define _Included_JniFuncMain
  6. #ifdef __cplusplus
  7. extern "C" {
  8. #endif
  9. /*
  10.  * Class: JniFuncMain
  11.  * Method: createJniObject
  12.  * Signature: ()LJniTest;
  13.  */
  14. JNIEXPORT jobject JNICALL Java_JniFuncMain_createJniObject
  15.   (JNIEnv *, jclass);

  16. #ifdef __cplusplus
  17. }
  18. #endif
  19. #endif

4、  编写C++代码 jnifunc.cpp


点击(此处)折叠或打开

  1. #include "JniFuncMain.h"
  2. #include <stdio.h>

  3. JNIEXPORT jobject JNICALL Java_JniFuncMain_createJniObject(JNIEnv * env, jclass clazz)
  4. {
  5.     jclass targetClass;
  6.     jmethodID mid;
  7.     jobject newObject;
  8.     jstring helloStr;
  9.     jfieldID fid;
  10.     jint staticIntField;
  11.     jint result;

  12. // C程序控制Java端代码

  13.     //1、访问类静态成员域,获取JniFuncMain类的staticIntField变量值
  14.     fid = env->GetStaticFieldID(clazz, "staticIntField", "I");
  15.     staticIntField = env->GetStaticIntField(clazz, fid);
  16.     printf("[CPP]获取JniFuncMain类的staticIntField值\n");
  17.     
  18.     //查找生成对象的类
  19.     targetClass = env->FindClass("JniTest");
  20. //该函数用于加载本地定义的类。它将搜索由CLASSPATH 环境变量为具有指定名
  21. //称的类所指定的目录和 zip 文件
  22. // FindClass的参数名必须是:类全名(即包名后跟类名,之间由“/”分隔)
  23.     
  24.     //2、查找构造方法
  25.     mid = env->GetMethodID(targetClass, "", "(I)V");
  26.         // 1."(I)V"是用javap反编译工具反编译JniTest的成员
  27.         // 获得的签名。GetMethodID方法会根据此签名找到该方法。
  28.         // 反编译class文件命令,例子: javap -s -p 类名
  29.         // 2. 第一个参数不是JNIEnv*类型是因为此代码是c++代码。原理类似于this指针。
  30.         // 3. 只有获得构造方法时第2个参数是<init>,其他的,直接传入方法名称即可。
  31.     //3、生成JniTest对象(返回对象的引用)
  32.     printf("[CPP]JniTest对象生成\n");
  33.     newObject = env->NewObject(targetClass, mid, 100);
  34.     
  35.     //4、调用对象的方法
  36.     mid = env->GetMethodID(targetClass, "callByNative", "(I)I");
  37.     result = env->CallIntMethod(newObject, mid, 200);
  38.     
  39.     //5、访问对象的成员变量,设置JniObject对象的intField值
  40.     fid = env->GetFieldID(targetClass, "intField", "I");
  41.     printf("[CPP]设置JniTest对象的intField值为200\n");
  42.     env->SetIntField(newObject, fid, result);
  43.     
  44.     //返回对象的引用
  45.     return newObject;
  46. }

5、  生成C共享库

D:\Users\lusi\JNI\JNI-2> cl  -I  "D:\Program Files\Java\jdk1.8.0_25\include" -I  "D

\Program Files\Java\jdk1.8.0_25\include\win32" –LD  jnifunc.cpp  -Fejnifunc.dll

6、  执行Java程序

D:\Users\lusi\JNI\JNI-2> java  JniFuncMain


阅读(1510) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~