利用Jni技术让C++调用Java程序
2013-12-31 09:34 chanrom 阅读(550) 评论(0) 编辑 收藏 举报查阅了很多资料,最终实现这一功能主要靠这两篇博文,这里特别感谢两位博主的分享:
使用JNI进行Java与C/C++语言混合编程(2)--在C/C++中调用Java代码
C++调用JAVA方法详解
代码基本copy于第一篇,但对于我的环境dev c++不是完全能够让程序跑起来。所以有些地方需要改动一下:
- 包含编译需要的两个头文件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文件夹下。
- 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"); }