当前位置: 首页 > news >正文

C++调用Java接口

一、配置Java环境

安装jdk,我这里使用jdk1.8 32位版本,下载地址:https://www.oracle.com/java/technologies/downloads/#java8-windows
image.png

下载安装后,设置环境变量:
image.png

JAVA_HOME
C:\Program Files (x86)\Java\jdk-1.8
image.png

设置Path:
image.png
image.png

新增三个:
%JAVA_HOME%\bin
%JAVA_HOME%\jre\bin
%JAVA_HOME%\jre\bin\client
image.png



二、创建Java类

打开IDEA创建一个工程:例如JavaDemo
image.png

创建类:MyJavaClass
image.png

public class MyJavaClass {// 成员方法1,带参数,有返回值public String getSomething(String str){return str + " hello";}// 成员方法2,带参数,有返回值public int addNumber(int a1, int a2){return a1 + a2;}// 成员方法3,带参数,没有返回值public void printSomething(String str){System.console().printf(str);}// 静态方法,带参数,有返回值public static String staticMethodExample(String str){return str + " static method hello";}
}

Main.java添加一些测试代码验证是否有问题:(为了避免MyJavaClass有问题,在这里调用一下MyJavaClass里的方法测试一下)
image.png

public class Main {public static void main(String[] args) {MyJavaClass myJavaClass = new MyJavaClass();String ret = myJavaClass.getSomething("Java");System.out.println("myJavaClass.getSomething return: " + ret);int num = myJavaClass.addNumber(1, 5);System.out.println("myJavaClass.addNumber return: " + num);myJavaClass.printSomething("Java");String ret2 = MyJavaClass.staticMethodExample("Java");System.out.println("MyJavaClass.staticMethodExample return: " + ret2);}
}

运行,得到结果:
image.png



三、生成jar

在项目中右键,选择Open Module Settings
image.png

选择Artifacts
image.png
image.png
image.png
image.png
image.png
image.png

最后,生成jar,在菜单栏选择 Build -> Build Artifacts
image.png

在菜单栏选择 Build -> Build Artifacts 后,在IDE的界面中随机在某个地方会出现下面的Build Artifact的弹窗,点击“Build
image.png

Build完成后,就会在 out/artifacts 目录下生成jar文件
image.png

注意:如果JaveDemo引用了其他第三方库,也是会被一起打包到jar里面的



四、C++调Java接口示例

使用VS创建一个C++工程
属性设置:C/C++ -> General -> Additional Include Directories 添加:
$(JAVA_HOME)\include
$(JAVA_HOME)\include\win32
image.png

Linker -> General -> Additional Library Directories 添加:
$(JAVA_HOME)\lib
image.png

Linker -> General -> Additional Library Directories 添加: jvm.lib

image.png

创建一个main.cpp,添加代码:

#include <iostream>#include "jni.h"int main() {std::string jarFile = "../../JavaDemo/out/artifacts/JavaDemo_jar/JavaDemo.jar";std::string optionString = "-Djava.class.path=" + jarFile;JavaVMOption options[1];options[0].optionString = const_cast<char*>(optionString.c_str());JavaVMInitArgs vm_args;memset(&vm_args, 0, sizeof(vm_args));vm_args.version = JNI_VERSION_1_8;vm_args.nOptions = 1;vm_args.options = options;vm_args.ignoreUnrecognized = false;JavaVM* jvm = nullptr;JNIEnv* env = nullptr;// 启动虚拟机long status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);if (status == JNI_ERR) {std::cout << "JNI_CreateJavaVM失败," << status << std::endl;return -1;}// 先获得class对象jclass cls = env->FindClass("MyJavaClass");     // 如果类带包名,这里需要加上包名,比如 com/example/MyJavaClass,把包名的.换成/if (cls == nullptr) {std::cout << "FindClass MyJavaClass 失败" << std::endl;return -1;}// 下面是调用成员方法和静态方法的示例,为了区分开来演示,用{}分开在两个作用域内。工作代码中不需要这样做。// 调用成员方法{// 查找构造函数并创建对象jmethodID constructor = env->GetMethodID(cls, "<init>", "()V");if (constructor == nullptr) {std::cout << "查找构造函数失败" << std::endl;return -1;}jobject myJavaClassObj = env->NewObject(cls, constructor);if (myJavaClassObj == nullptr) {std::cout << "MyJavaClass类对象创建失败" << std::endl;jvm->DestroyJavaVM();   // 后面的代码只要退出应该都需要先释放VMreturn -1;}// 一、调用成员方法 getSomething 的示例{// 1. 获取成员方法getSomething的IDjmethodID getSomethingMethodid = env->GetMethodID(cls, "getSomething", "(Ljava/lang/String;)Ljava/lang/String;");if (getSomethingMethodid == nullptr) {std::cout << "getSomethingMethodid获取失败" << std::endl;return -1;}// 2. 调用成员方法getSomethingjstring inputString = env->NewStringUTF("Test");    // 这是成员方法getSomething的参数jstring ret = (jstring)env->CallObjectMethod(myJavaClassObj, getSomethingMethodid, inputString);const char* str = env->GetStringUTFChars(ret, 0);std::cout << "成员方法getSomething返回:" << str << std::endl;env->ReleaseStringUTFChars(ret, 0);}// 二、调用成员方法 addNumber 的示例{// 1. 获取成员方法getSomething的IDjmethodID addNumberMethodid = env->GetMethodID(cls, "addNumber", "(II)I");if (addNumberMethodid == nullptr) {std::cout << "addNumberMethodid获取失败" << std::endl;return -1;}// 2. 调用成员方法getSomethingjint param1 = 1;jint param2 = 5;jint ret = (jint)env->CallObjectMethod(myJavaClassObj, addNumberMethodid, param1, param2);std::cout << "成员方法getSomething返回:" << ret << std::endl;}}// 调用静态方法{jmethodID methodId = env->GetStaticMethodID(cls, "staticMethodExample", "(Ljava/lang/String;)Ljava/lang/String;");if (methodId == nullptr) {std::cout << "获取静态方法staticMethodExample的id失败" << std::endl;return -1;}jstring inputString = env->NewStringUTF("Test");    // 这是静态方法staticMethodExample的参数jstring ret = (jstring)env->CallStaticObjectMethod(cls, methodId, inputString);const char* str = env->GetStringUTFChars(ret, 0);std::cout << "静态方法staticMethodExample返回:" << str << std::endl;env->ReleaseStringUTFChars(ret, 0);}// 释放jvmif (jvm){jvm->DestroyJavaVM();}return 0;
}

代码运行结果:
image.png

其中:

  1. 调用Java的成员函数,需要先创建对象,获取成员函数的MethodID,然后再调用成员函数;
  2. 调用Java的静态函数,不需要创建对象,直接获取静态方法的MethodID,再调用即可;
  3. GetMethodID和GetStaticMethodID获取方法ID时,需要填入方法名方法签名,具体转换如下表:

(1)基础类型:

Java TypeNative TypeSignature
bytejbyteB
charjcharC
doublejdoubleD
floatjfloatF
intjintI
shortjshortS
longjlongJ
booleanjbooleanZ
voidvoidV

(2)引用数据类型:

Java TypeNative TypeSignature
所有对象jobjectL+classname +;
ClassjclassLjava/lang/Class;
StringjstringLjava/lang/String;
ThrowablejthrowableLjava/lang/Throwable;
Object[]jobjectArray[L+classname +;
byte[]jbyteArray[B
char[]jcharArray[C
double[]jdoubleArray[D
float[]jfloatArray[F
int[]jintArray[I
short[]jshortArray[S
long[]jlongArray[J
boolean[]jbooleanArray[Z
  1. 方法签名组装方式:

    (参数类型1参数类型2…)返回值类型
    例如,(II)I 表示接受两个整数参数,返回一个整数。

    下面是一些方法签名的具体示例:
    int add(int a, int b) => (II)I
    String concat(String str1, String str2) => (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    void printMessage(String message) => (Ljava/lang/String;)V
    boolean isValid(int number) => (I)Z

    还可以通过 javap -s -p 指令获取对应的签名信息,例如,我在MyJavaClass.class生成的目录,执行: javap -s -p MyJavaClass
    image.png

  2. 更多参考:https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html



五、问题

  1. 下图是环境变量的问题,按照第一部分设置环境变量后,重启VS再试

image.png

  1. 32位与64位jdk不匹配的问题,如果C++程序是32位,jdk也要是32位,如果C++程序是64位,则jdk也需要为64位

image.png



六、其他

注意:开发环境可以安装完整的jdk,但是打包在其他电脑上运行,运行环境就只需要安装jre就可以

运行环境设置

jre下载地址:https://www.oracle.com/java/technologies/downloads/#jre8-windows
在这里插入图片描述

设置环境变量Path:
C:\Program Files (x86)\ava\latest\jre-1.8\bin
C:\Program Files (x86)\ava\latest\jre-1.8\bin\client



七、代码

https://gitee.com/jie-xio/cpp_samples/tree/master/CppCallJavaDemo



相关文章:

C++调用Java接口

一、配置Java环境 安装jdk&#xff0c;我这里使用jdk1.8 32位版本&#xff0c;下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/#java8-windows 下载安装后&#xff0c;设置环境变量&#xff1a; JAVA_HOME C:\Program Files (x86)\Java\jdk-1.…...

C# datetimePicker

1. 直接把控件拉到设计器中&#xff0c;此时不要调整控件的values属性&#xff0c;这样就可以 打开后每次默认显示当天日期。 2. 属性Format long长日期格式默认值short短日期格式Time时间格式custom自定义时间格式在customFormat这个属性设置&#xff0c;比如yyyy-MM-dd HH…...

AI有关的学习和python

一、基本概念 AIGC&#xff08;AI Generated content AI 生成内容&#xff09; AI生成的文本、代码、图片、音频、视频。都可以成为AIGC。 Generative AI&#xff08;生成式AI&#xff09;所生成的内容就是AIGC AI指代计算机人工智能&#xff0c;模仿人类的智能从而解决问题…...

前端node.js入门

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 Node.js 入门概览 什么是Node.js&#xff1f; 为什么选择Node.js&#xff1f; 基础安装与环境配置 安装…...

无需标注的数据集

0&#xff1a;人 1&#xff1a;自行车 2&#xff1a;汽车 3&#xff1a;摩托车 4&#xff1a;飞机 5&#xff1a;公交车 6&#xff1a;火车 7&#xff1a;卡车 8&#xff1a;船 9&#xff1a;交通信号灯 10&#xff1a;消火栓 11&#xff1a;停车标志 12&#xff1a;停车计时器…...

C# 抽象工厂模式

栏目总目录 概念 抽象工厂模式是一种创建型设计模式&#xff0c;它提供了一种创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类。在抽象工厂模式中&#xff0c;一个抽象的工厂类负责定义创建产品对象的接口&#xff0c;但是具体工厂类将负责创建具体的产…...

java中 两个不同类对象list,属性一样,如何copy

如果您有两个不同的类&#xff0c;但它们拥有相同的属性&#xff0c;并且您想要从一个类的列表复制到另一个类的列表&#xff0c;您可以使用以下方法&#xff1a; 使用循环&#xff1a; 您可以遍历原始列表&#xff0c;并为每个元素创建目标类的新实例。 使用 Stream API&…...

文件上传总结

一、原理 通过界面上的上传功能上传了一个可执行的脚本文件&#xff0c;而WEB端的系统并未对其进行检测或者检测的逻辑做的不够好&#xff0c;使得恶意用户可以通过文件中上传的一句话木马获得操控权 二、绕过方法 1>前端绕过 1.删除前端校验函数 checkFile() 2.禁用js…...

网页突然被恶意跳转或无法打开?DNS污染怎么解决?

前言 在网上冲浪时&#xff0c;我们时常会遭遇DNS污染这一区域性攻击&#xff0c;几乎无人能幸免。受影响时&#xff1a;尝试访问正规网站可能会被错误导向赌博、色情或其他恶意站点。 1.我们为什么需要DNS 当我们想要访问一个网站时&#xff0c;就像拨打朋友的电话号码一样…...

Matlab进阶绘图第65期—带分组折线段的柱状图

带分组折线段的柱状图是在原始柱状图的基础上&#xff0c;在每组柱状图位置处分别添加折线段&#xff0c;以进行对比或添加额外信息。 由于Matlab中未收录带分组折线段的柱状图的绘制函数&#xff0c;因此需要大家自行设法解决。 本文使用自制的BarwithGroupedLine小工具进行…...

EasyMedia转码rtsp视频流flv格式,hls格式,H5页面播放flv流视频

在本文中&#xff0c;我们将介绍如何使用 EasyMedia 将 RTSP 视频流转码为 FLV 和 HLS 格式&#xff0c;并在 H5 页面上播放 FLV 流视频。EasyMedia 是一个支持多种流媒体协议的开源项目&#xff0c;非常适合用于这种转码和流媒体传输的场景。 前提条件 已经安装并配置好 Eas…...

FPGA实验6: 有时钟使能两位十进制计数器的设计

一、实验目的与要求 1.. 熟练掌握使用原理图设计较复杂电路&#xff1b; 2. 学习原理图设计中总线的表示以及使用方法。 二、实验原理 运用Quartus II 集成环境下的图形设计方法设计有时钟使能的两位十进制计数器。进行波形仿真和分析、引脚分配并下载到实验设备上进行功能…...

C# 委托函数 delegate

在C#中&#xff0c;委托&#xff08;Delegate&#xff09;是一种特殊的类型&#xff0c;它可以持有对方法的引用。 委托是实现事件的基础。事件本质上是多播委托&#xff0c;允许多个方法被触发 委托允许你将方法作为参数传递给其他方法&#xff0c;或者将方法作为返回值从方法…...

Vue3响应式高阶用法之`shallowReadonly()`

Vue3响应式高阶用法之shallowReadonly() 在现代前端开发中&#xff0c;Vue3 提供了丰富的响应式 API 来帮助开发者更高效地管理状态和数据。其中&#xff0c;shallowReadonly() 是一个非常有用的工具&#xff0c;适用于需要部分只读状态的场景。本文将详细介绍 shallowReadonl…...

Windows系统安全加固方案:快速上手系统加固指南 (下)

这里写目录标题 一、概述二、IP协议安全配置启用SYN攻击保护 三、文件权限3.1 关闭默认共享3.2 查看共享文件夹权限3.3 删除默认共享 四、服务安全4.1禁用TCP/IP 上的NetBIOS4.2 ### 禁用不必要的服务 五、安全选项5.1启动安全选项5.2禁用未登录前关机 六、其他安全配置**6.1防…...

记一次因敏感信息泄露而导致的越权+存储型XSS

1、寻找测试目标 可能各位师傅会有苦于不知道如何寻找测试目标的烦恼&#xff0c;这里我惯用的就是寻找可进站的思路。这个思路分为两种&#xff0c;一是弱口令进站测试&#xff0c;二是可注册进站测试。依照这个思路&#xff0c;我依旧是用鹰图进行了一波资产的搜集&#xff…...

Java笔试面试题AI答之线程Thread(1)

答案来自 Kimi AI 目录 1. 进程和线程的区别&#xff1f;2. Java语言创建线程的方式有哪些&#xff1f;3. Java线程有哪几种可用状态&#xff1f;4. Java同步方法和同步代码块的区别&#xff1f;5. 在监视器(Monitor)内部&#xff0c;如何做线程同步的&#xff1f;6. 什么是死…...

2.5 C#视觉程序开发实例2----图片内存管理

2.5 C#视觉程序开发实例2----图片内存管理 1 目标效果视频 mat-buffer 2 Mat 数组的定义 3 图片内存使用场合说明 3.1 程序加载或者切换程序时 3.2 设定时&#xff0c;注册图片 例如注册一个线速的图片 注册流程说明 3.3 外部触发时采集最新图片或者按钮点击时触发拍照 …...

Java核心 - 深入理解 Java 枚举类

作者&#xff1a;逍遥Sean 简介&#xff1a;一个主修Java的Web网站\游戏服务器后端开发者 主页&#xff1a;https://blog.csdn.net/Ureliable 觉得博主文章不错的话&#xff0c;可以三连支持一下~ 如有疑问和建议&#xff0c;请私信或评论留言&#xff01; 前言 在Java中&…...

HOW - CSS 定义颜色值

目录 1. 十六进制颜色 (Hexadecimal Color)2. RGB 颜色 (RGB Color)3. HSL 颜色 (HSL Color)HSL 颜色模式示例 4. 预定义颜色名 (Named Colors)5. LCH 颜色 (LCH Color)6. Lab 颜色 (Lab Color)7. HWB 颜色 (HWB Color)8. CSS 颜色函数 (Color Function)9. CSS4 颜色模块中的其…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...