博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vs2008 c++ 调用java
阅读量:4154 次
发布时间:2019-05-25

本文共 3691 字,大约阅读时间需要 12 分钟。

参考:

计划第三篇写一个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); 

转载地址:http://gfeti.baihongyu.com/

你可能感兴趣的文章
php程序员看过来,这老外是在吐糟你吗?看看你中了几点!
查看>>
为什么说程序员是“培训班出来的”就是鄙视呢?
查看>>
码农吐糟同事:写代码低调点不行么?空格回车键与你有仇吗?
查看>>
阿里p8程序员四年提交6000次代码的确有功,但一次错误让人唏嘘!
查看>>
一道技术问题引起的遐想,最后得出结论技术的本质是多么的朴实!
查看>>
985硕士:非科班自学编程感觉还不如培训班出来的,硕士白读了?
查看>>
你准备写代码到多少岁?程序员们是这么回答的!
查看>>
码农:和产品对一天需求,产品经理的需求是对完了,可我代码呢?
查看>>
程序员过年回家该怎么给亲戚朋友解释自己的职业?
查看>>
技术架构师的日常工作是什么?网友:搭框架,写公共方法?
查看>>
第四章 微信飞机大战
查看>>
九度:题目1008:最短路径问题
查看>>
九度Online Judge
查看>>
九度:题目1027:欧拉回路
查看>>
九度:题目1012:畅通工程
查看>>
九度:题目1017:还是畅通工程
查看>>
九度:题目1034:寻找大富翁
查看>>
第六章 背包问题——01背包
查看>>
51nod 分类
查看>>
1136 . 欧拉函数
查看>>