Java调用c++的动态链接库正确方式,踩坑选手!

news/2024/11/24 22:52:03/

文章目录

  • 1、JNI是什么?需要怎么理解它?
  • 2、如何在idea和clion中操作使用?
    • 2.1Java中编写JNI接口
      • 2.1.1 通过指令自动生成
      • 2.1.2 自己编写c++头文件__(c++头文件以.h,源文件则是.cpp)
    • 3.1 使用Clion导入项目
      • 3.1.1CmakeLists.txt文件的配置
      • 3.1.2 安装toolchains
      • 3.1.3 编写c++代码。
  • 4.1 Java如何直接将float或者double改成二进制呢?

前言,前几个月泛泛的看了一下c++的相关书籍。在看的过程中,做几个例子啥的没啥感觉。但是在整合起来的过程中还是发现了蛮多问题。

1、JNI是什么?需要怎么理解它?

JNI (Java Native Interface,Java本地接口)是一种编程框架 ,使得Java虚拟机中的Java程序可以调用本地应用/或库,也可以被其他程序调用。 本地程序一般是用其它语言(C、C++或汇编语言等)编写的,并且被编译为基于本机硬件和操作系统的程序。
有些事情Java无法处理时,JNI允许程序员用其他编程语言来解决。例如,Java标准库不支持的平台相关功能或者程序库。也用于改造已存在的用其它语言写的程序,供Java程序调用。许多基于JNI的标准库提供了很多功能给程序员使用,例如文件I/O、音频相关的功能。当然,也有各种高性能的程序,以及平台相关的API实现,允许所有Java应用程序安全并且平台独立地使用这些功能。
理解:JNI是一种约束和规范,我们可以通过java调用动态链接库来实现java不好处理的场景。

2、如何在idea和clion中操作使用?

我这边使用的环境是vs2019、idea2021、clion2019。其他的版本目前没尝试,我估计大概都差不多,书写到这里只是做了一个demo。
Demo的场景是,通过java的jni标准库调用c++动态联,获取float或double的二进制数据,并返回String打印!
我这里踩过的坑不少,提前梳理一下:

  1. 使用clion生成了动态联,但是idea上面报错,内容为没有找到哪些数据。
  2. 使用c++ char数据,在答应的过程中始终无法得到相关数据,在java中打印始终为“”。
  3. clion中的toolchains配置
  4. 配置cmakelist错误,始终无法编译

上面的问题足足折磨我了好几天,因为在过程中,我只是需要做个demo,跑完Hello World之后。想到一个场景,就想去证实一下,没想到……,下面我整理一下我的过程:

2.1Java中编写JNI接口

首先需要使用到JNI中的关键字native关键字,类似和java中的interface一样。eg:

public class FloatAndDouble2Binary {public native String float2Binary(float v_f);public native String double2Binary(double v_d);static {System.loadLibrary("doubleAndFloat2binary");}public static void main(String[] args) {double d=3.14;String s = new FloatAndDouble2Binary().double2Binary(d);System.out.println("double:"+s);float f=3.14f;String sf = new FloatAndDouble2Binary().float2Binary(f);System.out.println("float:"+sf);}
}

这样我们就写好了接口,但是如何转换成c++的头文件呢?__有两种方式:

2.1.1 通过指令自动生成

进入到源文件的目录,在搜索框中输入cmd,进入控制台:

javac -h . DFUtils.java

然后在目录里面你会发现多了两个文件:一个以.h结尾的文件,一个以.class结尾的二进制文件。
Ps:将.h的文件放入到一个文件夹中,这里提前说过的。做个伏笔

2.1.2 自己编写c++头文件__(c++头文件以.h,源文件则是.cpp)

这里看多了或者写过c++文件的人就知道如何做了。推荐使用指令生成!

3.1 使用Clion导入项目

3.1.1CmakeLists.txt文件的配置

打开Clion工具,点击New CMake Project from Sources,此时会自动生成一个CMakeLists.txt配置的文件。


cmake_minimum_required(VERSION 3.15)  #cmake 兼容最低的版本
project(double) #项目名
set(CMAKE_CXX_STANDARD 14) #cmake 编译的版本
include_directories(.) #include //包括的路径 可以理解为环境变量
include_directories(F:/include)
include_directories(F:/include/win32)
include_directories(F:/include/win32/bridge)
add_library(doubleAndFloat2binary SHAREDcom_company_float_double_class_FloatAndDouble2Binary.cppcom_company_float_double_class_FloatAndDouble2Binary.h)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
#add_excutable(项目名 待编译的项目.c 待编译的项目.h),与add_library不要同时使用
#否则会出现编译错,又要生成动态链接又要生成可执行的文件,是不行的!

如果使用jni的,你会得到提示jni无法找到的问题。这时候你需要到你自己jdk的配置目录找到include文件夹,其目录为<JAVA_HOME>/include
在CMakeLists.txt 中加入include_directories(path)即可。

3.1.2 安装toolchains

clion的步骤:File-Settings-Build,Execution,Deployment-ToolChains,我这里最开始安装的Cygwin,但是编译出来的时32为的动态连,在64位的机器上会出错。找了N多资料,还是没有找到,最终下载安装了VS。
安装VS的版本也是有要求的,如果在Toolchains里面提示过高过低,你可以降低或者升级vs的版本即可解决
Environment的目录为你安装vs的根目录,clion的Toolchains会自动搜索,其中Architecture,选择你对应cpu的版本,Platforms目前还不知道目的,有知道的朋友可以帮忙填空。Version自动会进行选择,

3.1.3 编写c++代码。

//com_company_float_double_class_FloatAndDouble2Binary.cpp
#include <jni.h>
#include "com_company_float_double_class_FloatAndDouble2Binary.h"
#include <iostream>char* strChars;
template <typename T>
char* double2Template(T v);
char* value2Binary(char* point, int sof) {const int length = sof * 8+1;strChars = new char[length];int index = 0;for (int i = sof - 1; i >= 0; i--) {char item = point[i];for (int j = 7; j >= 0; j--) {strChars[index] = (item >> j & 1)+'0';index++;}}strChars[length-1]='\0';return strChars;
}template<typename T>
char* double2Template(T v) {int sof = sizeof(v);const int lengt = sof * 8 ;char* point = (char*)(&v);char* arry = value2Binary(point, sof);return arry;
}/** Class:     com_company_float_double_class_FloatAndDouble2Binary* Method:    float2Binary* Signature: (F)Ljava/lang/String;*/
JNIEXPORT jstringJNICALL Java_com_company_float_1double_1class_FloatAndDouble2Binary_float2Binary(JNIEnv *env, jobject obj, jfloat f) {int byteLen = sizeof(jfloat);double2Template(f);return env->NewStringUTF(strChars);
}/** Class:     com_company_float_double_class_FloatAndDouble2Binary* Method:    double2Binary* Signature: (D)Ljava/lang/String;*/
JNIEXPORT jstringJNICALL Java_com_company_float_1double_1class_FloatAndDouble2Binary_double2Binary(JNIEnv * env, jobject obj, jdouble d) {double2Template(d);return env->NewStringUTF(&*strChars);
}

如果按照我上面的全部编写成功,可以使用快捷键ctrl+F9或者使用[Build-Build Project]进行编译。此时会看到一个.dll的文件。

在java中添加引用dll的文件

static{System.load("文件名");
}

将文件赋值到<Java_HOME>/bin目录下,直接运行java调用(也可以在idea中导入dll的动态链接库,网上有很多博客可以参考)。

4.1 Java如何直接将float或者double改成二进制呢?

        //使用java 得到float的二进制数float f=3.14f;int ibyte= Float.floatToIntBits(f);StringBuilder sb=new StringBuilder();for (int i=31;i>=0;i--){sb.append(ibyte>>i&1);}// 或者是直接遍历// Integer.toBinaryString(ibyte);System.out.println(sb);

至此Java调用c++动态库就成功了。一个简单的Hello World就此就完结了。


http://www.ppmy.cn/news/147388.html

相关文章

基于555定时器的LED电子骰子设计

目录 零、前言 一、电路总体原理图 1.1所用仿真平台及电子元件 1.2整体原理图 二、主要元件及其工作原理介绍 2.1 555定时器 2.2 4017逻辑单元 三、现象展示 四、尾声 零、前言 自从研究生开学以来就一直在学各种算法&#xff0c;从来没有碰硬件的东西&#xff0c;今…

k1658停运_武汉局集团公司近期临时停运列车的公告

中国铁路武汉局集团有限公司关于2020年1月24日起至另有通知时止部分旅客临时停运列车的公告 1.2020年1月24日起至另有通知时止&#xff0c;汉口至荆门间T6701/2次停运。 2.2020年1月24日起至另有通知时止&#xff0c;汉口至荆门间K8101/4次停运。 3.2020年1月24日起至另有通知时…

S32K的bootloader CAN总线实现

本文摘要&#xff1a;本文章介绍如何使用NXP官方软件S32KDS实现CAN总线上的bootloader 开发平台&#xff1a;S32 Design Studio for ARM Version 2.2 SDK版本&#xff1a;S32_SDK_S32K1xx_RTM_3.0.0 使用芯片&#xff1a;S32K148 使用设备&#xff1a;图莫斯usb2can 源码免…

live555 调优总结

发送优化方面&#xff0c;主要就是调整live555的缓冲区大小和每次发送的数据大小&#xff0c;众所周知&#xff0c;流媒体发送的是各种大小的音视频数据&#xff0c;而这些数据大的几百k&#xff0c;小的就几个字节&#xff0c;如果每一个零散的数据都要走一遍发送循环&#xf…

vue中使用Echarts绘制K线图

一、需求问题 在开发项目中&#xff0c;我们可能会遇到这样的需求。在vue中使用Echarts绘制K线图&#xff0c;进行数据分析。下面是一个简单的K线图绘制&#xff0c;数据是伪造的&#xff0c;虽然不多&#xff0c;但是能够实现大致的K线图效果。 二、需求分析 对于使用Echar…

学妹为了学习数电,自制555芯片

大家好&#xff0c;我是小麦&#xff0c;相信很多小伙伴在上学的时候学过《数字电子技术》这门专业基础课&#xff0c;而在这里面&#xff0c;有一个非常经典的芯片就是555定时器。 今天我给大家分享一个很有其的项目&#xff0c;就是用分立元器件去实现一个比砖头还要大的555定…

【数据挖掘】K-NN 分类 ( 简介 | 分类概念 | K-NN 分类实例 | K-NN 分类准确度评估 | K-NN 分类结果评价指标 | 准确率 | 召回率 )

文章目录 I . K-NN 简介II . K-NN 分类III . K-NN 分类实例IV . K-NN 分类 准确性评估方法V . 保持法VI . k k k-交叉确认法VII . K-NN 分类结果评价指标VIII . 分类 判定 二维表IX . 准确率X . 召回率XI . 准确率与召回率关联XII . 准确率 与 召回率 综合考虑 I . K-NN 简介 …

live555中openRTSP用法

openRTSP A command-line RTSP client openRTSP是一个命令行程序&#xff0c;它可以用来打开&#xff0c;流化&#xff0c;接收并且录制指定的RTSP视频链接媒体流(如rtsp://开头的URL) (一个相关的程序“playSIP”可以用来播放或者录制一个SIP会话) 本文将要介绍如下内容 Bas…