1. SWIG是什么?
SWIG的官方网站是 http://www.swig.org/ 。
官方网站第一句话:SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages. ... ... SWIG is typically used to parse C/C++ interfaces and generate the 'glue code' required for the above target languages to call into the C/C++ code. ... ... SWIG is free software and the code that SWIG generates is compatible with both commercial and non-commercial projects.
翻译一下: SWIG是一种软件开发工具,可将用C和C ++编写的程序与各种高级编程语言相连接。... ... SWIG通常用于解析C / C ++接口并生成上述目标语言调用C / C ++代码所需的“胶水代码”。 ... ... SWIG是免费软件,SWIG生成的代码与商业和非商业项目兼容。
其中, “上述目标语言”,包括:脚本语言,如Javascript、Perl、PHP、Python、TCL和Ruby。非脚本语言,如C#、D、GO语言、Java、Lua、OCaml、Octave、Scilab和R。
也就是说,SWIG是 可以为其他语言比如Python、java等,生成能够调用使用C和C++编写的库的相关代码的 一个免费软件。
2. SWIG能做什么?
我个人认为,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做的事情,就是将你从“沉重枯燥易出错”的工作中解脱出来。
3. SWIG怎么用?
要想使用SWIG,需要先下载SWIG,可以在 https://sourceforge.net/projects/swig/files/ 下载自己操作系统对应的包。(如果感兴趣的话,官方也提供了源码以及在不同操作系统上的编译方法,自己可以动手修改编译。)
我使用的是Windows,因此我下载的是最新版本的 https://sourceforge.net/projects/swig/files/swigwin/swigwin-4.0.2/
下载完成之后并解压,然后配置SWIG的环境变量。配置完成之后,打开cmd窗口,输入swig 试试,是否配置好了。
先简单的看一下,swig怎么使用,这里以Android开发为例,以下是在Android Studio中进行的,这里默认NDK等相关开发环境已经准备好了,也已经建好了一个正常的APP Module,目录结构如下所示:
libs下的libmyfun.so(这里libmyfun.so跟上面第2节中的libmyfun.so不是同一个,这里的是个纯粹功能的库)为已经用C写好的so库,并且知道要使用so库中的函数为:int doFun();
(a). 先编写一个以 ".i"结尾的文件myswig.i,放到跟这个Module的build.gradle同一级目录(其实myswig.i可以放在任何位置),这个文件用于生成JNI对应的Java代码和C代码,myswig.i的内容为:
%module MySwig
%inline %{
extern int doFun();
%}
(b). 然后使用命令:
swig -java -package com.my.fun -outdir ../java/com/my/fun -o ./myfun_wrap.c myswig.i
//注意,这个命令中,是在配置好swig的环境变量之后,在myswig.i这个文件所在的目录下执行的
//可以通过swig -help 命令查看参数含义
//其中 -java 表示要产生java相关文件
//-package 生成java文件的包名
//-outdir 表示将产生的java文件输出到的目录
//-o 表示产生的C或C++文件路径
执行这个命令后,会生成几个文件:
myswig_wrap.c,MySwig.java,MySwigJNI.java
打开myswig_wrap.c文件之后发现里面发现有很多代码,其中最主要的代码为:
打开MySwigJNI.java 和 MySwig.java分别是:
这么看来,如果我们自己写JNI相关的代码,也基本是这样的代码。
(c). 最后在编写CMakeLists.txt文件,把生成myswig_wrap.c编译成libmyswig.so库,以及在MainActivity中使用MySwigJNI的doFun方法,运行一遍看看效果。
不过,不要忘了在java文件中加上 加载 System.loadLibrary("myswig"); 加载编译好的libmyswig.so库。
4. 最后
这里介绍的是SWIG最最基本的用法。
SWIG有一些团队学习成本,但它也能减少一些机械重复的编码工作。具体要不要在实际项目中使用SWIG,是仁者见仁智者见智的。
具体更多的用法可以参看官网:http://www.swig.org/
如果是做java或Android开发的,也可以看看:
http://www.swig.org/Doc1.3/Java.html
http://www.swig.org/Doc2.0/Android.html#Android_examples_intro
另外,https://www.jianshu.com/p/8d8fdb095f88 (Swig java Jni开发指南)写的也挺详细的。