SWIG介绍和使用

news2024/11/25 19:11:18

官网:https://www.swig.org/ github:https://github.com/swig

SWIG 是一种软件开发工具,可将用 C 和 C++ 编写的程序与各种高级编程语言连接起来。

SWIG 与不同类型的目标语言一起使用,包括常见的脚本语言,如 Javascript、Perl、PHP、Python、Tcl 和 Ruby。支持的语言列表还包括非脚本语言,例如 C#、D、Go 语言、Java,包括 Android、Lua、OCaml、Octave、Scilab 和 R。还支持多种解释和编译的 Scheme 实现(Guile、MzScheme/Racket) . SWIG 最常用于创建高级解释或编译的编程环境、用户界面,以及作为测试和原型设计 C/C++ 软件的工具。 SWIG 通常用于解析 C/C++ 接口并生成上述目标语言调用 C/C++ 代码所需的“胶水代码”。 SWIG 还可以以 XML 的形式导出其解析树。 SWIG 是免费软件,SWIG 生成的代码与商业和非商业项目兼容。

下载、安装:

https://www.swig.org/download.html

./configure --prefix=/usr \
            --without-maximum-compile-warnings &&
make
make install 

1、SWIG for java:

官网:SWIG and Java

SWIG 的 Java 扩展使得从 Java 访问现有 C/C++ 代码变得非常容易,因为 SWIG 为您编写了 Java 本机接口 (JNI) 代码。它与使用“javah”工具不同,因为 SWIG 将包装现有的 C/C++ 代码,而 javah 采用“本机”Java 函数声明并创建 C/C++ 函数原型。 SWIG 使用 Java 代理类包装 C/C++ 代码,如果您想从 Java 访问大量 C/C++ 代码,它非常有用。如果只需要一个或两个 JNI 函数,那么使用 SWIG 可能有点矫枉过正。 SWIG 使 Java 程序能够轻松地从 Java 调用 C/C++ 代码。从历史上看,SWIG 无法生成任何代码来从 C++ 调用 Java 代码。但是,SWIG 现在支持完整的跨语言多态性,并且在包装 C++ 虚拟方法时生成代码以从 C++ 调用到 Java。

LightGBM4j: a java wrapper for LightGBM,使用的就是SWIG。

https://github.com/metarank/lightgbm4j

1)SWIG和JNA的区别:

2)SWIG for java能做什么?

SWIG就是要为其他编程语言生成 能够调用 C和C++编写的库 的中间代码。 举个例子,如果你知道Java 可以通过JNI 调用C和C++,那么SWIG也就是 “做JNI的事情”。

这里先解释一下 “做JNI的事情”:当我们在进行Java开发时候,在某些情况下是要调用C开发的库。但Java代码是没办法直接调用C开发的库,需要做大致两个步骤的开发才可行:

第一步,你要写一个Java层的代码,加载so库,以及声明一个native方法:

//MyFunJNI.java文件,包名为: com.my.fun
public class MyFunJNI {
  static {
      System.loadLibrary("myfun");
  }
  public final static native int doFun();
}

第二步,你要编写一个C层代码,对应第一步MyFunJNI中的doFun方法,并调用到你想要使用的C开发的库中的函数 int c_fun():

/myjni.c
jint Java_com_my_fun_MyFunJNI_doFun(JNIEnv *env,jobject thiz){
    return c_fun();
}

然后将myjni.c编程库,比如libmyfun.so,将这个libmyfun.so和C编写的库,放在java程序运行时能加载到的位置。

这样java程序就能调用C开发的库中的方法了。在大部分情况下,第二步的代码编写是一个从Java翻译成C的枯燥无味的工作,尤其是里面涉及一些类型的转换工作,写的不熟悉的话还得自己动手查或者从别处copy。但如果是使用了SWIG,那就不需要我们自己动手写第一步和第二步中的相关代码了,因为SWIG可以帮我们生成。因此,我觉得SWIG做的事情,就是将你从“沉重枯燥易出错”的工作中解脱出来。

 2、SWIG使用:

1)假设我们要封装的C/C++文件如下,命名为example.c :

#include <time.h>
 double My_variable = 3.0;
 
 int fact(int n) {
     if (n <= 1) return 1;
     else return n*fact(n-1);
 }
 
 int my_mod(int x, int y) {
     return (x%y);
 }
 	
 char *get_time()
 {
     time_t ltime;
     time(&ltime);
     return ctime(&ltime);
 }

2)另外,我们还要定义一个接口定义脚本i文件(example.i):

%module example
 %{
 /* Put header files here or function declarations like below */
 extern double My_variable;
 extern int fact(int n);
 extern int my_mod(int x, int y);
 extern char *get_time();
 %}
 
 extern double My_variable;
 extern int fact(int n);
 extern int my_mod(int x, int y);
 extern char *get_time();

3)执行SWIG命令生成java对应的文件:

swig -java example.i

生成了如下两个java文件: 

查看:

public class example {
  public static void setMy_variable(double value) {
    exampleJNI.My_variable_set(value);
  }
  public static double getMy_variable() {
    return exampleJNI.My_variable_get();
  }
  public static int fact(int n) {
    return exampleJNI.fact(n);
  }
  public static int my_mod(int x, int y) {
    return exampleJNI.my_mod(x, y);
  }
  public static String get_time() {
    return exampleJNI.get_time();
  }
}
public class exampleJNI {
  public final static native void My_variable_set(double jarg1);
  public final static native double My_variable_get();
  public final static native int fact(int jarg1);
  public final static native int my_mod(int jarg1, int jarg2);
  public final static native String get_time();
}

从JAVA的角度讲,接口的封装已经完成,但native方法要调用相应的动态库要通过以下命令来打包。注意,这里是坑点。以下命令不能照搬,因为以下命令是要通过本地的JAVA环境的include目录中的动态库来进行编译,不同的环境要自己改成适合的路径。

4)gcc编译:

gcc -c -fPIC example.c example_wrap.c -I/usr/lib/jvm/jdk-11.0.9/include -I/usr/lib/jvm/jdk-11.0.9/include/linux

生成了example.o 和 example_Wrap.o

5)生成动态链接库:

gcc -shared -o example.so example.o example_wrap.o

生成了example.so

6)java中调用:

将SWIG生成的两个java文件(example.java和example_JNI.java)拷贝到java工程中,然后:

public class main {
   public static void main(String argv[]) {
     System.load("/home/kevin/Documents/Cpp/example.so");
     System.out.println(example.getMy_variable());
     System.out.println(example.fact(5));
     System.out.println(example.get_time());
   }
 }

注意这里也有坑,动态库的加载有两种方法,一是System.load加载绝对路径中的文件,一是System.loadLibrary加载系统库的默认路径。

SWIG初体验 - 知乎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/647524.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

redis集群-Redis(六)

上篇文章介绍了哨兵架构以及集群搭建。 哨兵架构&redisCluster-Redis&#xff08;五&#xff09;https://blog.csdn.net/ke1ying/article/details/131178880 redisCluster 接着上篇文章继续讲解&#xff0c;前面一个linux服务器已经有了8001和8004节点&#xff0c;现在继…

八大典型的黑盒测试方法已来袭,快快接住!

前言 有了软件缺陷的暴露&#xff0c;我们就需要通过各种软件测试的方法来查找出软件的漏洞&#xff0c;编写出测试用例&#xff0c;及时修改bug。 在下面的这篇文章中&#xff0c;我们将谈论八大典型的黑盒测试方法&#xff0c;一起来学习⑧&#x1f4a1; 一、等价类划分法…

【Python实战】Python采集王者皮肤图片

前言 我们上一篇介绍了&#xff0c;如何采集王者最低战力&#xff0c;本文就来给大家介绍如何采集王者皮肤&#xff0c;买不起皮肤&#xff0c;当个桌面壁纸挺好的。下面&#xff0c;我和大家介绍如何获取数据。 环境使用 python 3.9pycharm 模块使用 requests 模块介绍 re…

c++返回值使用引用的注意事项

c返回值使用引用的注意事项 问题原因返回函数的引用形参另外一个问题解决方法 问题 引用变量b接受到的值为无意义的数字。 原因 int& b returnYingyong();相当于&#xff1a; int i2 3; int& b i2; 销毁 i2;将局部变量作为返回值&#xff0c;导致引用b数据无意义…

【LInux】进程间通信(共享内存)

文章目录 system V共享内存shmget&#xff08;创建共享内存&#xff09;ftok&#xff08;key&#xff09;ipcs指令shmctl&#xff08;销毁共享内存&#xff09;shmat代码 共享内存 system V共享内存 共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间&am…

新能源突围,需要发力被忽视的中端品牌战场

作者 |张祥威 编辑 |德新 今年2月&#xff0c;受特斯拉等竞品降价影响&#xff0c;深蓝SL03销量下滑至4000台。深蓝的市场部上报长安中国&#xff0c;十天后开始降价&#xff0c;3月SL03销量重回正轨。 在巨头和新势力之间灵活腾挪&#xff0c;深蓝向外界展示了爆款制造的素质…

网络安全知识点梳理(期末不挂科)

网络安全复习知识点太多梳理不清晰&#xff1f;&#x1f44f;&#x1f3fb;&#x1f44f;&#x1f3fb;&#x1f44f;&#x1f3fb; 本文一篇帮你梳理清晰&#xff0c;内容覆盖整个大学网络安全知识点&#x1f44c;&#x1f3fb; 干货满满不看后悔&#x1f44d;&#x1f44…

leetcode 309.最佳买卖股票时机含冷冻期

题目描述 给定一个整数数组prices&#xff0c;其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票&#xff09;: 卖出股票后&#xff0c;你无法在第二天买入…

基于深度学习的高精度足球检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度足球检测识别系统可用于日常生活中或野外来检测与定位足球目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的足球目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型…

【Java基础学习打卡09】JRE与JDK

目录 引言一、JRE二、JDK三、JDK、JRE和JVM关系总结 引言 本文将介绍JRE、JDK是什么&#xff0c;以及JDK、JRE和JVM关系三者之间的关系。 一、JRE JRE全称为Java Runtime Environment&#xff0c;是Java应用程序的运行时环境。JRE包括Java虚拟机&#xff08;JVM&#xff09;、…

【数据结构】二叉树经典题目

1. 二叉树创建字符串 相信大部分人看了题目描述之后&#xff0c;都会和我一样一脸的懵逼。直到我看到了一个描述才恍然大悟 分为3种情况&#xff1a; 左右都为空 --省略右为空&#xff0c;左不为空 – 省略左为空&#xff0c;右不为空–不省略 这里复习一下二叉树的前序遍历…

Linux基本指令(四)

文章目录 一、新建(adduser)与删除(userdel)普通用户二、date指令三、find指令四、grep指令 一、新建(adduser)与删除(userdel)普通用户 前面我Linux登录时都是以root的身份登录的&#xff0c;从现在开始以普同用户登录&#xff0c;那么普通用户哪里来&#xff0c;是由root用户…

泰坦陨落2找不到msvcr120.dll的解决方法

msvcr120.dll是的动态链接库文件之一。它在Windows操作系统中发挥着重要的作用&#xff0c;它提供了应用程序所需的各种功能和方法。 该文件返回编译后的代码所需的支持库。msvcr120.dll包含用于C / C编译器生成的应用程序所需的重要功能&#xff0c;包括数学函数&#xff0c;…

第六节 容器(列表)

文章目录 列表掌握知识点1.1 概述1.1.1 语法格式 1.2 列表的循环遍历1.2.1 for 循环遍历列表1.2.2 while 循环遍历列表 1.3 列表的常见操作1.3.1 列表增加元素1.3.2 列表删除元素1.3.3 列表查询元素 1.4 列表的排序1.5 列表的嵌套1.6 练习 随机分班1.7 练习 判断字符结尾1.8 扩…

华为OD机试真题 JavaScript 实现【最长子字符串的长度】【2022Q4 100分】,附详细解题思路

一、题目描述 给你一个字符串s&#xff0c;字符串s首尾相连组成一个环形&#xff0c;请你在环形中找出‘o’字符出现了偶数次最长子字符串的长度。 二、输入描述 输入一串小写字母组成的字符串。 三、输出描述 输出一个整数。 四、解题思路 题目要求在给定的环形字符串中…

HTML中嵌入JavaScript代码的三种方式

第一种方式: <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>HTML中嵌入JavaScript的第一种方式</title> </head> <body> <!-- 1.要实现的功能…

Unix/Linux操作系统的最强入门科普(经典)

今天这篇文章&#xff0c;我们来聊聊操作系统&#xff08;Operating System&#xff09;。 说到操作系统&#xff0c;大家都不会陌生。我们天天都在接触操作系统——用台式机或笔记本电脑&#xff0c;使用的是windows和macOS系统&#xff1b;用手机、平板电脑&#xff0c;则是…

深度学习入门——神经网络

神经网络 神经网络是一种受到人脑神经系统启发的机器学习模型。它由一系列相互连接的人工神经元组成&#xff0c;这些神经元以层次结构排列。每个神经元接收来自上一层神经元的输入&#xff0c;并根据权重和激活函数对输入进行加权处理&#xff0c;然后将输出传递给下一层神经…

【框架源码】Spring源码解析之Bean创建源码流程

问题&#xff1a;Spring中是如何初始化单例bean的&#xff1f; 我们都知道Spring解析xml文件描述成BeanDefinition&#xff0c;解析BeanDefinition最后创建Bean将Bean放入单例池中&#xff0c;那么Spring在创建Bean的这个过程都做了什么。 Spring核心方法refresh()中最最重要…

uniapp小程序订单页面UI

前言 之前用模板写了订单页面&#xff0c;由于需求改了导致这个页面做更新麻烦&#xff0c;弄了一下午&#xff0c;索性全部删除了自己写了&#xff0c;上面的tabs用的是b-ui框架写的&#xff0c;其他的都是原生写法。 &#x1f64f;如果这篇文章对你有帮助还请收藏点赞关注&…