简介

实际工程可能存在如下部分:业务接口需要编程高效的语言(如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-Tools or-tools/constraint_solver.i at stable · google/or-tools · GitHub
libtorrent4j https://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

Swig/CPP2Java相关推荐

  1. swig error : Unrecognized option -doxygen Ubuntu 安装 swig-3.0.12

    1. 下载 下载地址:https://sourceforge.net/projects/swig/ 2. 安装 tar -xzvf swig-3.0.12.tar.gzcd swig-3.0.12# ...

  2. pip install faiss-gpu失败unable to execute ‘swig‘: No such file or directory

    1. 安装报错 unable to execute 'swig': No such file or directory error: command 'swig' failed with exit s ...

  3. linux+swig+python,linux下使用swig让python调用C++(复杂版:包括多文件调用和链接库)...

    第一次用swig,网上找了各种资料,比如 http://www.cnblogs.com/kaituorensheng/p/4464117.html 入门可以看上面这个链接 但要么过于简单要么过于复杂 ...

  4. SWIG和PInvoke学习(1)

    1. 简介 SWIG是个帮助使用C或者C++编写的软件能与其它各种高级编程语言进行嵌入联接的开发工具. SWIG能应用于各种不同类型的语言包括常用脚本编译语言例如Perl, PHP, Python, ...

  5. SWIG,C#沟通C++的桥梁

    研究Topic Maps时,找到了有人写好的C#类库,于是研究之,一看之下大惊失色,这代码是人写起来的么,那么凌乱,不禁对作者产生了强烈地敬仰--那么乱都管理得过来..... 后来发现这个有提示说是用 ...

  6. Swig在Mac OS X上的安装

    网上有很多类似文章介绍Swig怎么在Mac OS X上安装和配置,一般来说就是: 下载pcre,configure & make & make install 下载swig,confi ...

  7. 在Python中调用C++,使用SWIG

    http://www.coder4.com/archives/2141 SWIG:Simplified Wrapper and Interface Generator,顾名思义,就是将C/C++包装为 ...

  8. swig模板 PHP,nodejs前端模板引擎swig入门

    相对于jade,我还是更喜欢swig前端模板引擎,jade虽然语法简练高效了不少,但是在我这最大的问题是 他没有一个html该有的样子... 所以我还是决定使用swig,页面结构,样子都是熟悉的样子, ...

  9. SWIG:SWIG的简介、安装、使用方法之详细攻略

    SWIG的简介.安装.使用方法之详细攻略 目录 SWIG的简介 SWIG的安装 SWIG的使用方法 SWIG的简介 SWIG是一种软件开发工具,它将C和C++编写的程序与各种高级编程语言连接起来.SW ...

最新文章

  1. STM32串口接收数据
  2. linux下监控用户的操作记录
  3. 常见模块设计--数据字典
  4. 苹果电脑通过密钥对的方式登录linux系统
  5. 【Top】Plan (updating...)
  6. 如何只用一个小时定制一个行业AI 模型?
  7. Java:月份的中英文转换
  8. java中的工厂模式_java中工厂模式详解和使用方法
  9. 我该用 Java 12 还是坚持 Java 11?
  10. WPF 基础到企业应用系列2——WPF前世今生
  11. linux源代码剖析之二boot
  12. 【数据预测】基于matlab鸟群算法优化BP神经网络数据预测【含Matlab源码 1772期】
  13. MD4、MD5、SHA1、HMAC、HMAC_SHA1区别
  14. 第5章 演绎推理与归纳推理
  15. 怎样建网站?(超详细)
  16. 税号输入框 将input框中的输入自动转化成半角大写
  17. MySQL数据库基础详解
  18. 和人工智能交往,算不算爱情?
  19. SQL优化(三):子查询和IN,EXISTS用法和优化方法
  20. zip和tgz以及exe的区别

热门文章

  1. 华为4月11号 南研所 面经。(已拿offer)
  2. nginx重启报错:nginx: [error] open() “/usr/local/nginx/logs/nginx.pid“ failed (2: No such file or directo
  3. python中的self
  4. Ubuntu和windows系统下安装odoo16 社区版和企业版附带安装视频
  5. 自然语言-知识图谱调研结论
  6. 如何把图片制作生成网站连接(URL)
  7. Android 8.0 SurfaceFlinger
  8. VC知识库的一篇文章
  9. swing-组件tooltip测试及美化
  10. SFuzz: Slice-based Fuzzing for Real-Time Operating Systems