java c/cpp互相调用实例(c/cpp调用java )

最近在学习JNI方面的知识,转载这篇文章,作为入门的一些参考,方便以后查看,原文地址: http://www.iteye.com/topic/460152本文是 java c/cpp互相调用实例(java调用c/cpp)的续集c/cpp调用java。 

计划第三篇写一个java安装程序实例(客户端无jre环境的安装包),以解决java程序(软件)安装不方便的问题,使java程序安装也傻瓜化。 

直接进入正题: 

完成本实例需要下列工具/环境: 
1、java环境 
2、c/cpp编辑器。windows下推荐用vs/vc++,我用的是vs2008。linux下gcc/g++ 

从 C/CPP 程序调用 Java 代码需要四个步骤 : 
一 编写 Java 代码。 
二 编译 Java 代码。 
三 编写 C/C++ 代码。 
四 运行本机 C/C++ 应用程序。 

1、编写java代码 

为了达到示范作用,java方法我用两个,一个是静态方法,一个是普通方法。 

C2java.java 
Java代码   收藏代码
  1. package com.testJni.testDemo;  
  2.   
  3. public class C2java {  
  4.     public C2java(){  
  5.         super();  
  6.     }  
  7.     public static int add(int a,int b) {  
  8.         return a+b;  
  9.     }  
  10.     public boolean judge(boolean bool) {  
  11.         return !bool;  
  12.     }  
  13.   
  14. }  

静态方法的好处是我不用实例化,直接可以调用方法。调用起来比较简单,不容易出错。 

2、编译java代码 

javac 命令。(略) 

3、编写 C/C++ 代码 

我想在c/cpp中直接生成一个exe然后窗口输出结果,所以我就建立一个exe工程。编辑器jni环境是上篇已经搭建好的,所以这里只需要少量配置就可以了。好了,我们先建立一个工程: 

打开vs2008,新建一 win32 console App 工程 
 
键入工程名字c2java,点击OK,出来窗口点击next,选取console app 
 
点击完成。到这里先不忙编码实现,我们先把环境搭建好,右键工程属性,选取 linker -->input,在右边窗口添加依赖jvm.lib,这个lib的位置在你%JAVA_HOME%/lib 下。如果你的路径中同我一样包含空格(例如Program Files)记得用引号括起来。 
 
打开stdafx.h文件添加 
C++代码   收藏代码
  1. #include <iostream>  
  2. #include <jni.h>  
  3.   
  4. #ifdef _WIN32  
  5. #define PATH_SEPARATOR ';'  
  6. #else  
  7. #define PATH_SEPARATOR ':'  
  8. #endif  

打开c2java.cpp,键入下面的代码 
C++代码   收藏代码
  1. using namespace std;  
  2.   
  3. int main()  
  4. {  
  5.       
  6.   JavaVMOption options[1];  
  7.   JNIEnv *env;  
  8.   JavaVM *jvm;  
  9.   JavaVMInitArgs vm_args;  
  10.   long status;  
  11.   jclass cls;  
  12.   jmethodID mid;  
  13.   jint square;  
  14.   jboolean not;  
  15.     jobject jobj;  
  16.   
  17.   options[0].optionString = "-Djava.class.path=.";  
  18.   vm_args.version = JNI_VERSION_1_2;  
  19.   vm_args.nOptions = 1;  
  20.   vm_args.options = options;  
  21.   status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);  
  22.   if (status != JNI_ERR)  
  23.   {  
  24.         cls = env->FindClass("com/testJni/testDemo/C2java");  
  25.     if(cls !=0)  
  26.     {   
  27.                 mid = env->GetStaticMethodID( cls, "add""(II)I");  
  28.         if(mid !=0)  
  29.         {    
  30.                     square = env->CallStaticIntMethod( cls, mid, 5,5);  
  31.                     std::cout << square << std::endl;  
  32.           }  
  33.                 mid = env->GetMethodID(cls,"<init>","()V");  
  34.                 if(mid !=0)  
  35.         {    
  36.                     jobj=env->NewObject(cls,mid);  
  37.                     std::cout << "init ok" << std::endl;  
  38.           }  
  39.                 mid = env->GetMethodID( cls, "judge","(Z)Z");  
  40.                 if(mid !=0)  
  41.         {    
  42.                     not = env->CallBooleanMethod(jobj, mid, 1);  
  43.                     if(!not){  
  44.                         std::cout << "Boolean ok" << std::endl;  
  45.                     }  
  46.         }  
  47.                   
  48.     }  
  49.   
  50.     jvm->DestroyJavaVM();  
  51.    return 0;  
  52.   }  
  53.   else  
  54.     return -1;  
  55.   
  56. }  

下面解释下上面的代码: 
JavaVMOption options[] 具有用于 JVM 的各种选项设置。声明的 JavaVMOption options[] 数组足够大,就能容纳我们希望使用的所有选项。在本实例中,我们使用的选项就是类路径选项。 
JNIEnv *env 表示 JNI 执行环境。 
JavaVM *jvm 是指向 JVM 的指针。我们主要使用这个指针来创建、初始化和销毁 JVM。JavaVMInitArgs vm_args 表示可以用来初始化 JVM 的各种 JVM 参数。 
设置参数后,创建我们的jvm : 
  status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); 
成功返回0,不成功返回JNI_ERR。 
创建完成后,我们就可以查找我们的class了,因为我们的java类一般都有包,所以我们也要加上包路径com/testJni/testDemo/C2java 

在这里我们会使用到java的一个命令javap ,这个命令有什么用那,我们用javap -s -p C2java看看 
 
打开jni.h我们会发现,Signature就是sig,也就是GetStaticMethodID( cls, "add", "(II)I")方法的第三个参数。GetStaticMethodID表示调用static方法,GetMethodID调用普通方法。下面就是传入参数,打出结果。 
在看jni.h的时候我们注意到有 CallStaticXXXMethod() 和 CallXXXMethod() 之类的方法。这些方法分别代表调用静态方法和成员方法,用方法的返回类型(例如,Object、Boolean、Byte、Char、Int、Long 等等)代替变量 XXX。 
静态方法和普通方法不同之处就是普通方法必须要先实例化一个java对象,调用构造器的时候方法的名称为“<init>”。 

下面的代码就不用我再解释了,先是new一个实例出来,然后调用实例的方法。 

最后记得销毁jvm。 

代码解释完了,我们build下这个工程,生成c2java.exe。 

4、运行exe 

因为我们生成的exe需要调用jvm.dll初始化,为了使运行的exe不报错误,我们把%JAVA_HOME%/jre/bin/server也加进path目录。方便系统自动搜索jvm.dll。 
运行结果: 
 

最后补充:本实例并没有涉及到java的异常、java c/cpp的编码转换问题,对于异常问题,C里没有异常,请使用jni的异常处理函数。编码转换问题上篇已有介绍,此处略去。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值