浏览 28844 次
锁定老帖子 主题:c/cpp调用java方法 实例
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-09-01
----------c/cpp调用java 本文是javaJNI调用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 package com.testJni.testDemo; public class C2java { public C2java(){ super(); } public static int add(int a,int b) { return a+b; } public boolean judge(boolean bool) { return !bool; } } 静态方法的好处是我不用实例化,直接可以调用方法。调用起来比较简单,不容易出错。 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文件添加 #include <iostream> #include <jni.h> #ifdef _WIN32 #define PATH_SEPARATOR ';' #else #define PATH_SEPARATOR ':' #endif 打开c2java.cpp,键入下面的代码 using namespace std; int main() { JavaVMOption options[1]; JNIEnv *env; JavaVM *jvm; JavaVMInitArgs vm_args; long status; jclass cls; jmethodID mid; jint square; jboolean not; jobject jobj; options[0].optionString = "-Djava.class.path=."; vm_args.version = JNI_VERSION_1_2; vm_args.nOptions = 1; vm_args.options = options; status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); if (status != JNI_ERR) { cls = env->FindClass("com/testJni/testDemo/C2java"); if(cls !=0) { mid = env->GetStaticMethodID( cls, "add", "(II)I"); if(mid !=0) { square = env->CallStaticIntMethod( cls, mid, 5,5); std::cout << square << std::endl; } mid = env->GetMethodID(cls,"<init>","()V"); if(mid !=0) { jobj=env->NewObject(cls,mid); std::cout << "init ok" << std::endl; } mid = env->GetMethodID( cls, "judge","(Z)Z"); if(mid !=0) { not = env->CallBooleanMethod(jobj, mid, 1); if(!not){ std::cout << "Boolean ok" << std::endl; } } } jvm->DestroyJavaVM(); return 0; } else return -1; } 下面解释下上面的代码: 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的异常处理函数。编码转换问题上篇已有介绍,此处略去。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-09-28
请问有试过在linux环境下运行这个例子吗?
|
|
返回顶楼 | |
发表时间:2009-09-29
xxboy 写道 请问有试过在linux环境下运行这个例子吗?
linux下肯定不会成功,您不会在linux下拿这个例子试验了一下吧? |
|
返回顶楼 | |
发表时间:2009-10-01
console???? 多说些可以? 比如 dll, windows gui app
|
|
返回顶楼 | |