vs2008 c++ 调用java

135 篇文章 2 订阅

参考:http://zhuyx808.iteye.com/blog/460152

计划第三篇写一个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的异常处理函数。编码转换问题上篇已有介绍,此处略去。



if   Cannot open include file: 'jni.h': No such file or directory

if you have this problem with the jni there is one really simple way to solve it.

1.) go to your project properties

2.) navigate in the tree to "Configuration Properties->C/C++" then look at the first entry "Additional Include Directories"

3.) in there enter the path: "<JDK-Version-Path>\include";"<JDK-Version-Path>\include\win32"

以上还是有错误

将jvm.dll和msvcr100.dll拷贝至程序目录下

在程序上下添加:HINSTANCE hInstance = ::LoadLibraryA("C:\\Program Files\\Java\\jdk1.7.0_01\\jre\\bin\\server\\jvm.dll");

::FreeLibrary(hInstance); 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值