利用JNI在vs2010上实现c++调用Java类方法
这几天由于项目需要,需要在使用到在c++中调用Java代码,也就是所谓的 ,网上看了一下教程,基本用的编译器是vc6.0, 个人一直不喜欢用6.0,所以就在vs2010上倒腾了一遍整个过程,折腾了好久,也遇到了很多问题,还好最后是成功了
get 新技能!!!特写此博客作为记录。
环境:win7/win8.1 , vs2010, jdk_x86(64位的在使用中一直不能加载jvm.dll)
软件安装:
本文默认大家都已安装vs2010或更高版本,这里主要讲一下jdk的安装。 先从官网下载最新版本的Windows版的32位的sdk,如下图箭头所示:
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
双击应用程序——**下一步**——更改路径到 `D:\Java\jdk1.8.0_66 或者任意其他位置,如下:
继续下一步----再更改路径,如下
再下一步,加载完以后点击关闭就OK了!!!
*************************************分割线*****************************************
配置环境变量
鼠标 右击计算机----属性---高级系统设置---环境变量。。。如下
新建 java_home 和 classpath
变量名 java_hame
变量值 D:\Java\jdk1.8.0_66
变量名 classpath
变量值 D:\Java\jdk1.8.0_66\lib\dt.jar ;D:\java\jdk1.8.0_66\lib\tools.jar
点击path 添加 D:\Java\jdk1.8.0_66\lib;D:\Java\jdk1.8.0_66\jre\bin\server;D:\Java\jdk1.8.0_66\bin``
在磁盘任意位置新建文本文档,命名为 c_call_j.java ,随便写个小代码如下
[java] view plaincopy
- package test;
- public class c_call_j {
- public static int intMethod(int n) {
- return n*n;
- }
- public static double doubleMethod(double a,double b) {
- return a+b;
- }
- }
win+R 打开cmd,
编译Java代码 javac F:\C++\code\test\c_call_j.java
在输入 javap -s -p F:\C++\code\test\c_call_j.class 获得方法的签名
*************************************分割线*****************************************
打开vs2010,新建一个 win32控制台程序,源代码--添加--新建项,新建一个cpp文件,复制下面代码
-
//new.cpp
-
//
-
#include "windows.h"
-
#include "jni.h"
-
#include <string>
-
#include <iostream>
-
using namespace std;
-
int main()
-
{
-
int res; //虚拟机标示
-
JavaVMInitArgs vm_args; //表示可以用来初始化 JVM 的各种 JVM 参数。
-
JavaVMOption options[3]; //JavaVMOption options[] 具有用于 JVM 的各种选项设置
-
JavaVM *jvm; // 是指向 JVM 的指针,我们主要使用这个指针来创建、初始化和销毁 JVM
-
JNIEnv *env; //表示 JNI 执行环境
-
jmethodID mid; //类中方法的ID
-
options[0].optionString = "-Djava.compiler=NONE";
-
//设置classpath,如果程序用到了第三方的JAR包,也可以在这里面包含进来
-
options[1].optionString = "-Djava.class.path=F:\\C++\\code ";
-
//设置显示消息的类型,取值有gc、class和jni,如果一次取多个的话值之间用逗号格开,如-verbose:gc,class
-
//该参数可以用来观察C++调用JAVA的过程,设置该参数后,程序会在标准输出设备上打印调用的相关信息
-
options[2].optionString = "-verbose:NONE";
-
vm_args.version = JNI_VERSION_1_8; //设置版本号
-
vm_args.nOptions = 3;
-
vm_args.options = options;
-
//该参数指定是否忽略非标准的参数,如果填JNI_FLASE,当遇到非标准参数时,JNI_CreateJavaVM会返回JNI_ERR
-
vm_args.ignoreUnrecognized = JNI_TRUE;
-
//定义一个函数指针,下面用来指向JVM中的JNI_CreateJavaVM函数
-
typedef jint (WINAPI *PFunCreateJavaVM)(JavaVM **, void **, void *);
-
const wchar_t szJvmPath[]=L"D:\\Java\\jdk1.8.0_66\\jre\\bin\\client\\jvm.dll";
-
//加载JVM.DLL动态库
-
HINSTANCE hInstance = ::LoadLibrary(szJvmPath);
-
if (hInstance == NULL)
-
{
-
cout<< "LoadLibrary False"<<endl;
-
cout<<::GetLastError()<<endl;
-
return -2;
-
}
-
//取得里面的JNI_CreateJavaVM函数指针
-
PFunCreateJavaVM funCreateJavaVM = (PFunCreateJavaVM)::GetProcAddress(hInstance, "JNI_CreateJavaVM");
-
//调用JNI_CreateJavaVM创建虚拟机
-
res = (*funCreateJavaVM)(&jvm, (void**)&env, &vm_args);
-
if (res < 0)
-
{
-
return -1;
-
}
-
//查找类,返回JAVA类的CLASS对象
-
jclass cls = env->FindClass("test/JNI_cCalljava_test");
-
//根据类的CLASS对象获取该类的实例
-
jobject obj = env->AllocObject(cls);
-
if(cls==0){
-
cout<<"can't find the class\n";
-
return -2;
-
}
-
if(cls !=0)
-
{
-
//获取类中的方法,最后一个参数是方法的签名,通过javap -s -p [\path\filename.class] 获得
-
mid = env->GetStaticMethodID(cls, "intMethod", "(I)I");
-
if(mid !=0)
-
{
-
//构造参数并调用对象的方法
-
jint square = env->CallStaticIntMethod(cls, mid, 8);
-
cout<<"Result of intMethod :"<< square<<endl;
-
}
-
mid = env->GetStaticMethodID(cls, "doubleMethod", "(DD)V");
-
if(mid !=0)
-
{
-
double nt = env->CallObjectMethod(obj, mid, 8.8, 2.3);
-
cout<<"Result of doubleMethod: "<< nt<<endl;
-
}
-
}
-
//销毁虚拟机并释放动态库
-
jvm->DestroyJavaVM();
-
::FreeLibrary(hInstance);
-
return 0;
-
}
代码里注释很详细,不作过多解析,这时候还不能运行,需要修改vs的配置。
点击 视图--属性管理器--项目名--Debug|win32和release|win32
分别在包含目录和库目录添加
包含目录: D:\Java\jdk1.8.0_66\include;D:\Java\jdk1.8.0_66\include\win32
库目录:D:\Java\jdk1.8.0_66\lib
然后 Ctrl+F5 执行
成功运行。。。
本文参考:https://blog.****.net/u010803748/article/details/53114246