用C++调用jar包以及一些注意事项
1.打出一个漂亮的jar包
(1)我创建的java工程目录:
(2)编写JAVA代码
此处我写了三个函数,main()、add()、toUppercase()
package com.yxyhard.test;
public class Test {
public static void main(String[] args) {
Test test = new Test();
// test add
System.out.printf("1 + 2 = %d\n", test.add(1, 2));
// test toUpperCase
String greeting = "hello, world!";
System.out.printf("Upper case of \"%s\" is \"%s\"\n",
greeting, test.toUpperCase(greeting));
}
public int add(int num1, int num2) {
return num1 + num2;
}
public String toUpperCase(String str) {
return str.toUpperCase();
}
}
(3)直接在java中打jar包
file-Project Strcture
点击artifacts , +,填入要保存的路径,点击OK,则可在设置的路径下成功创建一个jar包
(4)验证jar包是否生成成功
在jar包路径下打开cmd,输入命令java -jar JINTest.jar,如果cmd窗口出现所写代码的输出内容,则说明生成jar包成功
2.C++调用jar包
(1)首先准备需要用到的Jdk中的文件:jin.h、jin_md.h、JVM.dll
路径分别为:D:\Java\jdk1.8.0_261\include\jin.h
D:\Java\jdk1.8.0_261\include\win32\jin_md.h
D:\Java\jdk1.8.0_261\jre\bin\server\JVM.dll
我不成熟的做法是将两个.h文件copy到我的C++头文件下,直接在主函数中include调用
(2)编写C++代码,调用jar包
#include "jni.h"
#include <Windows.h>
#include<iostream>
using namespace std;
int main()
{
/* 设置 JVM 参数 */
JavaVMInitArgs vmArgs;
vmArgs.version = JNI_VERSION_1_8;\
const int OPTION_COUNT = 2;
vmArgs.nOptions = OPTION_COUNT;
JavaVMOption options[OPTION_COUNT] = { 0 };
// classpath 指定为我们要调用的 jar 包路径
//options[0].optionString = "-Djava.class.path=G:\\projects\\java\\JNITest\\test.jar";
options[0].optionString = "-Djava.class.path=D:\\JINTest\\JINTest.jar";
options[1].optionString = "-Xmx1024m"; // 最大堆大小
vmArgs.options = options;
vmArgs.ignoreUnrecognized = JNI_TRUE;
/* 启动 JVM */
//HMODULE hModule = LoadLibrary(TEXT("G:\\Java\\jre1.8.0_131\\bin\\server\\jvm.dll"));//加载jvm库
//D:\Java\jdk1.8.0_261\jre\bin\server D:\Java\pre\bin\server
HMODULE hModule = LoadLibrary(TEXT("D:\\Java\\pre\\bin\\server\\jvm.dll"));
if (hModule == NULL)
{
cout << "LoadLibrary False" << endl;
return -1;
}
typedef jint(JNICALL *CreateJavaVMFuncPtr)(JavaVM **pvm, void **penv, void *args);
CreateJavaVMFuncPtr CreateJavaVM = (CreateJavaVMFuncPtr)GetProcAddress(hModule, "JNI_CreateJavaVM");
JavaVM *jvm = nullptr;
JNIEnv *env = nullptr;
jint res = (*CreateJavaVM)(&jvm, (void**)&env, &vmArgs);
if (res < 0)
{
return -1;
}
/* 调用 class */
// 找到 class
//jclass class_Test = env->FindClass("com/cynhard/test/Test");
jclass class_Test = env->FindClass("com/yxyhard/test/Test");
jmethodID methodId_main = env->GetStaticMethodID(class_Test, "main", "([Ljava/lang/String;)V");
env->CallStaticVoidMethod(class_Test, methodId_main, "");
// 释放资源
jvm->DestroyJavaVM();
FreeLibrary(hModule);
return 0;
}
3.一些注意事项:
(1)编译C++代码时JVM.dll文件调用失败
解决方法:
可能是平台和dll文件之间不兼容,于是将"解决方案平台"改为X64(如下图)
(2)代码中GetStaticMethodID的参数不确定
解决办法:
打开cmd,cd到java工程目录下,如果没有class文件,则用 javac Test.java 生成class文件,再输入javap -s Test.class ,即可得到结果(如下图)。每个函数有对应的参数,我的代码对应的main函数,因此用main函数对应的参数([Ljava/lang/String;)V
以上就是所有的C++通过JIN调用jar包的过程,记录一下,供以后参考。
参考文档:https://blog.csdn.net/u011304970/article/details/75713209?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.controls