代码改变世界

利用Jni技术让C++调用Java程序

2013-12-31 09:34  chanrom  阅读(550)  评论(0编辑  收藏  举报

   查阅了很多资料,最终实现这一功能主要靠这两篇博文,这里特别感谢两位博主的分享

使用JNI进行Java与C/C++语言混合编程(2)--在C/C++中调用Java代码

C++调用JAVA方法详解

  代码基本copy于第一篇,但对于我的环境dev c++不是完全能够让程序跑起来。所以有些地方需要改动一下:

  1. 包含编译需要的两个头文件jni.h,jni_md.h通过设置系统环境的方式没有成功,所以直接在dev工程里添加这两个头文件。只要安装了jdk这两个文件都会有。jni.h在D:\Program Files\Java\jdk1.7.0_15\include文件夹下,jni_md.h在D:\Program Files\Java\jdk1.7.0_15\include\win32文件夹下。
  2. dev工程添加这两个头文件之后,源文件这么写(主要参考第一篇博文的代码,再次感谢,尊重原创),改动:

          a) 获取jvm动态库的地方改动了一些:

              

                 以及

             

          b) 头文件包含些使用 #include "jni.h"

  源码如下:

         

#include "jni.h"
#include <string.h>
#include <stdio.h>
#include "windows.h"
#include <iostream>

// 环境变量PATH在windows下和linux下的分割符定义
#ifdef _WIN32
#define PATH_SEPARATOR ';'
#else
#define PATH_SEPARATOR ':'
#endif


int main(void)
{
    //定义一个函数指针,下面用来指向JVM中的JNI_CreateJavaVM函数 
    typedef jint (WINAPI *PFunCreateJavaVM)(JavaVM **, void **, void *); 
    
    JavaVMOption options[1];
    JNIEnv *env;
    JavaVM *jvm;
    JavaVMInitArgs vm_args;
    
    long status;
    jclass cls;
    jmethodID mid;
    jfieldID fid;
    jobject obj;
    
    options[0].optionString = "-Djava.class.path=.";
    memset(&vm_args, 0, sizeof(vm_args));
    vm_args.version = JNI_VERSION_1_6;
    vm_args.nOptions = 1;
    vm_args.options = options;
    
     //加载JVM.DLL动态库 
    HINSTANCE hInstance = ::LoadLibrary("D:\\Program Files\\Java\\jdk1.7.0_15\\jre\\bin\\client\\jvm.dll");
    //HINSTANCE hInstance = ::LoadLibrary("jvm.dll");
     if (hInstance == NULL)  
    {  
        std::cout << "false" << std::endl;
        return false;  
    }
    std::cout << "Load Library OK..." << std::endl;
        //取得里面的JNI_CreateJavaVM函数指针  
    PFunCreateJavaVM funCreateJavaVM = (PFunCreateJavaVM)::GetProcAddress(hInstance, "JNI_CreateJavaVM");      
    // 启动虚拟机
    status = (*funCreateJavaVM)(&jvm, (void**)&env, &vm_args);
    
    
    if (status != JNI_ERR)
    {
        std::cout << "status is OK..." << std::endl;
        // 先获得class对象
        cls = env->FindClass("Sample");
        if (cls != 0)
        {
            std::cout << "Find Class OK..." << std::endl;
            // 获取方法ID, 通过方法名和签名, 调用静态方法
            mid = env->GetStaticMethodID(cls, "sayHello", "(Ljava/lang/String;)Ljava/lang/String;");
            if (mid != 0)
            {
                std::cout << "Get Static Method OK..." << std::endl;    
                const char* name = "World";
                jstring arg = env->NewStringUTF(name);
                jstring result = (jstring)env->CallStaticObjectMethod(cls, mid, arg);
                const char* str = env->GetStringUTFChars(result, 0);
                printf("Result of sayHello: %s\n", str);
                env->ReleaseStringUTFChars(result, 0);
            }
            
            /*** 新建一个对象 ***/
            // 调用默认构造函数
            //obj = env->AllocObjdect(cls); 
            
            // 调用指定的构造函数, 构造函数的名字叫做<init>
            mid = env->GetMethodID(cls, "<init>", "()V");
            obj = env->NewObject(cls, mid);
            if (obj == 0)
            {
                printf("Create object failed!\n");
            }
            /*** 新建一个对象 ***/
            
            // 获取属性ID, 通过属性名和签名
            fid = env->GetFieldID(cls, "name", "Ljava/lang/String;");
            if (fid != 0)
            {
                const char* name = "icejoywoo";
                jstring arg = env->NewStringUTF(name);
                env->SetObjectField(obj, fid, arg); // 修改属性
            }
            
            // 调用成员方法
            mid = env->GetMethodID(cls, "sayHello", "()Ljava/lang/String;");
            if (mid != 0)
            {
                std::cout << "Get Method OK..." << std::endl;
                jstring result = (jstring)env->CallObjectMethod(obj, mid);
                const char* str = env->GetStringUTFChars(result, 0);
                printf("Result of sayHello: %s\n", str);
                env->ReleaseStringUTFChars(result, 0);
            }
        }
        
        jvm->DestroyJavaVM();
        ::FreeLibrary(hInstance);
        system("pause");
        return 0;

    }
    else
    {
        printf("JVM Created failed!\n");
        return -1;
    }
    
    system("pause");
}