您的位置:首页 > 编程语言 > Java开发

java c/cpp互相调用实例----------c/cpp调用java

2013-12-06 23:41 375 查看
计划第三篇写一个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代码


 




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;   
    }   
  
}  

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文件添加

C++代码


 




#include <iostream>   
#include <jni.h>   
  
#ifdef _WIN32   
#define PATH_SEPARATOR ';'   
#else   
#define PATH_SEPARATOR ':'   
#endif  

#include <iostream>
#include <jni.h>

#ifdef _WIN32
#define PATH_SEPARATOR ';'
#else
#define PATH_SEPARATOR ':'
#endif


打开c2java.cpp,键入下面的代码

C++代码


 




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;   
  
}  

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





大小: 39.9 KB




大小: 25.2 KB




大小: 57.8 KB




大小: 21.7 KB




大小: 3.9 KB
c2java.rar (3.5 KB)

下载次数: 392
查看图片附件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JAVA C 曲沐阳