Swig/CPP2Java

news/2024/12/5 1:14:36/

简介

实际工程可能存在如下部分:业务接口需要编程高效的语言(如Python、Java等),易于部署维护;而核心算法部分,某些场景需要高效计算,会使用性能高效的语言(如C/C++等)。

对于上述场景,“粘合剂”工具可以将语言打包,实现跨语言调用。例如Java/Python可以使用Swig转换后的C/C++代码,Python可以使用JPype等调用Java代码。这种跨语言调用的场景能帮助我们解决例如不同语言间性能差异、存量代码等问题。

本文主要记录、介绍使用Swig工具转换C++为Java代码中的一些常用技巧、问题及其解决方式等。

官方手册

Swig(4.0)用户手册:

SWIG Users Manualhttps://www.swig.org/Doc4.0/Contents.html#Contents

环境搭建&基础

朋友分享的Swig入门教程,此处不再赘述:

Swig超详细入门教程(Java调用C/C++, CMake)——更新于2021.12_ymzhu385的博客-CSDN博客_swig教程

Java-Cpp(包含了Swig/Jna/Jni)的Example代码,在github有个较为全面的仓库:

GitHub - remram44/java-cpp-example: Example of using C++ classes from Java. Showcases SWIG, JNA and JNI

本文后续的代码将以该github的exmaple代码为基础,进行扩展

Cpp2Java工程模板

Swig工程构建相对比较简单:

输入:C/C++代码 + cpp2java.i(Swig语法文件)
输出:Java代码(对应语言的代码)

所以我们的主要目的是学习cpp2java.i如何编写。想要全面学习swig/java .i语法的同学可以参看上文提到的官方手册,或相关开源项目,例如:

开源项目主要.i链接
Google OR-Toolsor-tools/constraint_solver.i at stable · google/or-tools · GitHub
libtorrent4jhttps://github.com/aldenml/libtorrent4j/blob/master/swig/libtorrent.i

本文摘要部分常用功能(语法)。

常用关键词概述

关键词概述
include基础关键词,可以关联多个.i文件,与C++中inlcude类似
template最常见的使用方式是template转换stl中的容器类(例如vector等)
extend在目标语言(java)扩展自定义类接口(不影响C++代码)
pragma(java)

%pragma(java) jniclassimports 可以为JNI添加import

%pragma(java) jniclasscode 可在JNI中插入java代码

typemap

typemap可以自定义跨语言数据转换,例如java中的int,在特定的场景下可在C++中自定义转换为long long(是否有必要有待商榷)。

参考:Typemaps

常用C++容器转换

在官方手册中,提供了一份较为常见的转换表:

核心思想是具体化C/C++容器中的模板,例如set<T> -> set<int>等。大部分容器均可通过类似方法转换:

%include "std_vector.i"
%include "std_string.i"
%include "std_map.i"namespace std {%template(IntVector) vector<int>;%template(Str2StrMap) std::map<std::string, std::string>;
};

类型扩展

部分场景,我们需要为自定义类(或依赖类)在Java中添加或重命名接口,例如c++中的map使用[]随机访问,而在java中可以重载为get访问。如下是开源仓库(libtorrent4j,boost_map.i)的案例:

namespace boost {
namespace container {template<class Key, class T>
class map
{
public:bool empty() const;void clear();std::int64_t size() const;%extend{# ...T& get(Key const& k){return $self->operator[](k);}# ...}
};}}

代码块

swig提供使用

%pragma(java) jniclasscode

添加内嵌代码块,一个较为常用的场景是加载动态库,例如官方文档中提到的

%pragma(java) jniclasscode=%{static {try {System.loadLibrary("example");} catch (UnsatisfiedLinkError e) {System.err.println("Native code library failed to load. \n" + e);System.exit(1);}}
%}

当需要在静态代码段中import不同包的类时,例如xgboost(XGBoostJNI)的 NativeLibLoader(XGBoost中NativeLibLoader与XGBoostJNI在同一个包中,不需要导入):

  static {try {NativeLibLoader.initXGBoost();} catch (Exception ex) {logger.error("Failed to load native library", ex);throw new RuntimeException(ex);}}

使用如下关键词import NativeLibLoader

%pragma(java) jniclassimports
%pragma(java) jniclassimports=%{
import ml.dmlc.xgboost4j.java.NativeLibLoader;
%}

常见问题

1. CMakeList-JDK环境问题

Could NOT find JNI (missing: JAVA_AWT_LIBRARY JAVA_JVM_LIBRARY
  JAVA_INCLUDE_PATH JAVA_INCLUDE_PATH2 JAVA_AWT_INCLUDE_PATH)

主要是CMake没识别到Java环境路径(或没安装),导致以下语句出错了

FIND_PACKAGE(JNI REQUIRED)

Stackoverflow上比较全面的回答了:

java - CMake could not find JNI - Stack Overflow

这边补充一个方案(部分用WSL1的同学即是设置了JAVA_HOME可能也找不到路径):

set(JAVA_DIR "your/jdk/path")set(JAVA_AWT_LIBRARY "${JAVA_DIR}/lib/libjawt.so")
set(JAVA_JVM_LIBRARY "${JAVA_DIR}/lib/server/libjvm.so")
set(JAVA_INCLUDE_PATH "${JAVA_DIR}/include")
set(JAVA_INCLUDE_PATH2 "${JAVA_DIR}/include/linux")
set(JAVA_AWT_INCLUDE_PATH "${JAVA_DIR}/include")

2. operator异常:

Warning 503: Can't wrap 'operator =' unless renamed to a valid identifier.

可选择如下方式处理:

%rename(eq) operator==;# or %ignore operator=;

Reference

[1] SWIG Users Manual

[2] GitHub - google/or-tools: Google's Operations Research tools

[3] https://github.com/dmlc/xgboost

[4] https://github.com/aldenml/libtorrent4j


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

相关文章

【数组】力扣75题:颜色分类

【数组】力扣75题&#xff1a;颜色分类力扣75题&#xff1a;颜色分类解法一&#xff1a;最简单&#xff0c;直接计算解法二&#xff1a;单指针法解法三&#xff1a;0&#xff0c;1双指针法解法四&#xff1a;0&#xff0c;2双指针法建议在看题目之前先了解数组的具体知识点&…

MATLAB算法实战应用案例精讲-【数模应用】概率生成模型(Generative Model)

前言 知识储备 表征学习 背后的核心思想representation learning ,不是试图直接对高维样本空间建模,而是使用一些低维潜在空间来描述训练集中的每个观察,然后学习一个映射函数,该函数可以在潜在空间中取一个点,将其映射到原始域中的一个点。换句话说,潜在空间中的每个…

[acwing周赛复盘] 第 88 场周赛20230128

[acwing周赛复盘] 第 88 场周赛20230128 一、本周周赛总结二、 4800. 下一个1. 题目描述2. 思路分析3. 代码实现三、4801. 强连通图1. 题目描述2. 思路分析3. 代码实现四、4802. 金明的假期1. 题目描述2. 思路分析3. 代码实现六、参考链接一、本周周赛总结 在T2卡了半天&#…

Python爬虫(2)-Selenium控制浏览器

Selenium中提供了不少的方法来操作浏览器 Selenium控制浏览器1.打开浏览器2.打开浏览器后可以控制浏览器前进和后退就使用3.浏览器刷新4.浏览器切换网页窗口5.关闭页面和退出浏览器6.设置窗口大小7.获取窗口位置8.最大化窗口9.最小化窗口11.无窗口运行10.全屏11.屏幕截图12.元素…

一名普通22届本科毕业生|前端程序员|22年年终总结

文章目录22年上半年&#xff1a;最后的学生时光隔离实习币基金迷茫困惑难受不要去想人生意义读书景点环境的力量再次隔离返校入职前的学习22年下半年&#xff1a;上班工作生活总结本来准备在22年年末写的&#xff0c;奈何那段时间工作太忙没抽出时间。现在是23年的1月27日&…

创建大量TCP连接时会受到什么因素的限制?

1.文件描述符资源 用户级限制 我们可以使用ulimit命令查看系统允许当前用户进程打开的文件数限制&#xff1a; ulimit -n 我们可以使用 ulimit -n 文件数 来修改不过这种设置是临时的&#xff0c;只在当前的session中有效。为永久修改用户级文件描述符数限制&#xff0c;可以…

网站如何进行整站优化?

如果要做优化或者选择性优化&#xff0c;一定要区分关键词优化和全站优化&#xff0c;米贸搜整理如下&#xff0c;希望可以帮助到你&#xff1a;一、全站优化的概念:1.一般认为&#xff0c;全站点优化是指通过SEO技术&#xff0c;使其网站成为搜索引擎中的权威站点。当达到效果…

【c语言进阶】动态内存管理知识大全(下)

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏c语言学习 &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是对我最大的激励和…