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

Java项目调用C/C++ SDK的方案汇总

Java项目调用C/C++ SDK的方案汇总

  • 背景
  • 调研
    • JNI
    • JNative
    • JNA
    • JavaCPP

背景

Java项目中需要调用到一个C++项目,于是对目前通用的解决方案做了一些调研,这里做一个汇总。

调研

JNI

JNI:Java Native Interface,JNI是一套编程接口,用来实现Java代码与本地的C/C++代码进行交互。

流程:

在这里插入图片描述

class文件生成C++头部文件(Test.h)示例,相关命令:

javac -h . MathJniTest.java

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "MathJniTest.h"
/* Header for class MathJniTest */

/*
 * Class:     MathJniTest
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_MathJniTest_add
  (JNIEnv *, jclass, jint x, jint y) {
      return x + y;
  }

/*
 * Class:     MathJniTest
 * Method:    sub
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_MathJniTest_sub
  (JNIEnv *, jclass, jint x, jint y) {
      return x - y;
  }
int main(int argc, const char* argv[]){

  }

关于头部文件的C++实现示例:

#include "Test.h"
/* Header for class MathJniTest */

/*
 * Class:     MathJniTest
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_MathJniTest_add
  (JNIEnv *, jclass, jint x, jint y) {
      return x + y;
  }

/*
 * Class:     MathJniTest
 * Method:    sub
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_MathJniTest_sub
  (JNIEnv *, jclass, jint x, jint y) {
      return x - y;
  }
int main(int argc, const char* argv[]){

  }

缺点&难点:需要对现有的语音SDK进行修改,增加Java编译后的头部文件及C++的实现,在这部分的代码中调用C++对应函数方法,并重新打包SDK

JNative

JNative:基于JNI的进一步封装

官方文档:http://jnative.free.fr/SPIP-v1-8-3/article.php3?id_article=4

下载第三方包(JNative),引入jar及dll(linux下是.so 动态库文件)
调用对应API实现

CJNative.dll为业务实现的dll文件,sub为方法名称

#include <iostream>


int sub (int x, int y) {
      return x - y;
  }


int main()
{
    int a = sub(1, 3);
     std::cout << a;
    return 0;
}
System.setProperty("jnative.debug", "true");
        System.setProperty("jnative.loadNative","C:\\Windows\\SysWOW64\\JNativeCpp.dll");
        JNative n3 = null;
        try {
            n3 = new JNative("CJNative.dll", "sub");
			// 设置返回类型
            n3.setRetVal(Type.INT);
			// 设置第一个参数值
            n3.setParameter(0, 1);
            n3.setParameter(1,8);
            n3.invoke();
            System.out.println("例3:outputString = "+n3.getRetVal());

        } catch (NativeException | IllegalAccessException e) {
            e.printStackTrace();
        }

优点:简单易用

缺点:仅支持windows下的32位系统及linux系统,缺乏完善的文档,并且2006年后不再维护

JNA

JNA:同样是JNI的封装升级

官方文档:https://github.com/java-native-access/jna

同样定义好.h 头部文件

#ifndef JNA_TEST_H
#define JNA_TEST_H

#ifdef __cplusplus
extern "C"
{
#endif
	__declspec(dllexport) int sub(int a, int b);



#ifdef __cplusplus
}
#endif
#endif //JNA_TEST_H

Java项目中定义好对应的接口,及加载对应的库(windows下为dll文件)

public interface JNAInterface extends Library {

    JNAInterface INSTANCE = Native.load(
            "D:\\test\\jna\\Jna.dll*",
            JNAInterface.class
    );

    int sub(int a,int b);
}

执行

public static void main(String[] args) {
//        Method[] methods = JNAInterface.INSTANCE.getClass().getDeclaredMethods();
//        for (Method method : methods) {
//            System.out.println(method.getName());
//        }
        System.out.println(JNAInterface.INSTANCE.sub(1, 3));
    }

优点:使用简单、文档比较完善且还在持续维护中

JavaCPP

JavaCPP:通过自动生成Java类和本地方法的方式,将C/C++代码包装为Java可调用的接口。

官方文档:https://github.com/bytedeco/javacpp/wiki/Mapping-Recipes

优点:自动生成Java类和本地方法。
缺点:相较于传统JNI,需要修改的业务逻辑 Java 代码会更多,需要考虑内存管理问题。

备注:感觉这个方式还是有一定的上手成本的,而且对于一些C++项目,如果入参和返参是一些很复杂的对象(或指针),转换难度比较大,笔者在实践过程中,碰了很多坑,最终是放弃了。


http://www.kler.cn/a/154917.html

相关文章:

  • TVBox 网络接口
  • 31-Shard Allocation Awareness(机架感知)
  • javaWeb小白项目--学生宿舍管理系统
  • SkyWalking-安装
  • 【论文阅读】WaDec: Decompiling WebAssembly Using Large Language Model
  • 【深度学习】学习率介绍(torch.optim.lr_scheduler学习率调度策略介绍)
  • 力扣题:字符串的反转-11.23
  • 盘点25个Html游戏Game源码网页爱好者不容错过
  • 前端面试JS— JS数据类型及相关内容
  • Linux 基础认识
  • 【每日一题】拼车+【差分数组】
  • DQN原理及PyTorch实现【强化学习】
  • java使用poi读写excel(处理上下标和科学计数法)
  • PriorityQueue类
  • 大数据基础设施搭建 - 业务数据同步策略
  • Linux shell中的函数定义、传参和调用
  • c++的函数对象和适配器
  • 目标检测YOLO系列从入门到精通技术详解100篇-【目标检测】单目视觉估计
  • 富文本编辑器(wangEditor 5)
  • Chat-GPT原理
  • 93基于matlab的萤火虫算法优化支持向量机(GSA-SVM)分类模型
  • Python中的split()、rsplit()、splitlines()的区别
  • opencv学习三:保存图片
  • 一起学docker系列之十四Dockerfile微服务实践
  • 《opencv实用探索·八》图像模糊之均值滤波简单理解
  • 【性能测试】稳定性/并发压力测试的TPS计算+5W并发场景设计...