SWIG(Simplified Wrapper and Interface Generator)是一個將C/C++接口轉換爲其餘語言接口的工具,從而能夠講C/C++的庫集成到其餘語言的系統中。目前SWIG已經能夠支持Python, Java, C#,Ruby,PHP,R語言等十多種語言。
本文介紹一下在Liuux平臺上如何將C++接口轉換爲Java接口。
1、首先先編寫一個C++的動態庫。
代碼以下:
一、接口文件定一個。
C++沒有像Java/C#同樣的interface關鍵詞,可是能夠用虛基類來定義接口個,虛基類一樣是隻有定義,沒有實現類,它的功能現放在繼承類中實現。
二、Geometry接口的實現類GeometryImpl
三、GeometryFactory接口的實現類GeometryFactoryImpl
此時的目錄結構爲:
include 存放.h文件
src 存放.cpp文件
四、編寫makefile,編譯動態庫
將makefile文件放到src目錄下,而後進入src目錄,執行make命令,編譯so庫。
#make
編譯完成後將生成libgemt.so動態庫。
這個C++庫用到了C++裏面的虛基類,純虛函數,繼承,C函數,靜態變量等概念。下面就看一下SWIG如何將這個C++的so庫轉換爲Java接口。
2、利用SWIG將C++接口轉換爲Java接口
一、SWIG接口文件(.i)
SWIG須要編寫一個後綴爲.i的接口文件,把C++接口的定義寫在.i文件中,也能夠將C++的頭文件include到.i文件中。這裏咱們將C++接口文件GeometryAPI.h include到.i文件中,文件名爲gemt4j.i。
module是模塊名。SWIG將C函數經過Java的JNI轉換爲JAVA方法,這些方法都以靜態方法的方式封裝到一個與模塊名同名的Java類中。
新建一個swig文件夾,將gemt4j.i文件存放到swig文件夾中。此時的目錄結構爲:
一、生成java類和wrap文件
編寫好.i文件,就能夠用swig生成java類和C++接口的wrap文件。
執行一下命令
#swig -c++ -java -package com.test -outdir ./ -I../include gemt4j.i
swig參數說明:
1)-c++ -java
告訴swig將C++接口轉換爲java接口。若是是將C接口轉換爲java接口,就不須要-c++,直接寫 swig -java就能夠。
2)-package
生成的java類的包的名稱
3) -I
gemt4j.i中include的.h文件的路徑
4)gemt4j.i
swig的.i文件
執行這條命令後,將在swig路徑下生成幾個文件
1)gemt4j_wrap.cxx
C++文件,包裝器文件。它將C++類的方法轉換爲C的函數。
2)gemt4j.java
這是與剛纔定義的module同名的一個類。
3)gemt4jJNI.java
打開這個文件能夠看到,C++類的方法都轉化爲Java的靜態方法。
4)其餘與C++類同名的Java類
每個C++類都被轉化爲與之對應的Java類,而且類名,方法明徹底同樣。
二、編譯gemt4j_wrap.cxx文件爲so庫
1) java頭文件
編譯gemt4j_wrap.cxx須要用到jni的頭文件jni.h
在個人機器上jdk安裝在/opt/jdk1.5.0_20/下,
須要包行兩個路徑:
1)/opt/jdk1.5.0_20/include/
2) /opt/jdk1.5.0_20/include/linux/
2) libgemt.so庫
還須要連接剛纔編譯好的libgemt.so庫
編寫makefile文件
生成libgemt4j.so庫,jni就是經過這個庫調用libgemt.so庫中的類和方法的。
到如今爲止,就經過SWIG將C++接口轉換爲Java接口。
3、使用SWIG生成的Java接口
一、編譯Java文件
進入swig目錄,SWIG生成的Java文件如今都在這裏。
#javac *.java
生成class文件。
剛纔咱們設定的java包是com.test
建立com/test目錄,將class文件移動到com/test目錄下,而後打包
#cd swig
#tar -cvf gemt4j.jar ./com
生成gemt4j.jar包
二、將libgemt4j.so放到java的library path路徑下。
能夠經過下面的方式查一下java的library path路徑
我這裏的library pah爲:/opt/jdk1.5.0_20/jre/lib/i386
把libgemt4j.so放到這個路徑下便可。
三、編寫java代碼。
說明:
System.loadLibrary("gemt4j");
用於裝載libgemt4j.so庫。
其餘代碼與普通的java無異。
編譯java文件:
#javac -cp /home/hawk/code/swig/dll/java/gemt4j.jar test.java
執行test程序
#java -cp /home/hawk/code/swig/dll/java/gemt4j.jar:/home/hawk/code/swig/dll/java test
輸出結果爲:
GeometryImpl
能夠看出,實現了Java調用C++類庫libgemt.so
本文介紹一下在Liuux平臺上如何將C++接口轉換爲Java接口。
1、首先先編寫一個C++的動態庫。
代碼以下:
一、接口文件定一個。
C++沒有像Java/C#同樣的interface關鍵詞,可是能夠用虛基類來定義接口個,虛基類一樣是隻有定義,沒有實現類,它的功能現放在繼承類中實現。
- #ifndef __GEOMETRY_API_H__
- #define __GEOMETRY_API_H__
- //===========================================================================
- class Geometry;
- class GeometryFactory;
- //---------------------------------------------------------------------------
- /*
- * 說明:幾何對象類
- */
- class Geometry
- {
- public:
- Geometry(){}
- virtual ~Geometry(){}
- public:
- virtual const char* GetType() = 0;
- virtual void Release() = 0;
- };
- //---------------------------------------------------------------------------
- /*
- * 說明:幾何對象工廠類
- */
- class GeometryFactory
- {
- public:
- GeometryFactory(){}
- virtual ~GeometryFactory(){}
- public:
- virtual Geometry* CreateGeometry() = 0;
- };
- //---------------------------------------------------------------------------
- /*
- * 說明:C函數,用於獲取GeometryFactory類的一個實例
- */
- extern "C"
- {
- GeometryFactory* meGetGeometryFactoryInstance();
- }
- //===========================================================================
- #endif
二、Geometry接口的實現類GeometryImpl
- #ifndef __GEOMETRY_IMPL_H__
- #define __GEOMETRY_IMPL_H__
- #include "GeometryAPI.h"
- class GeometryImpl : public Geometry
- {
- public:
- GeometryImpl();
- virtual ~GeometryImpl();
- public:
- virtual const char* GetType();
- virtual void Release();
- };
- #endif
- #include "GeometryImpl.h"
- GeometryImpl::GeometryImpl()
- {
- }
- GeometryImpl::~GeometryImpl()
- {
- }
- const char* GeometryImpl::GetType()
- {
- return "GeometryImpl";
- }
- void GeometryImpl::Release()
- {
- delete this;
- }
三、GeometryFactory接口的實現類GeometryFactoryImpl
- #ifndef __GEOMETRY_FACTORY_IMPL_H__
- #define __GEOMETRY_FACTORY_IMPL_H__
- #include "GeometryAPI.h"
- class GeometryFactoryImpl : public GeometryFactory
- {
- public:
- GeometryFactoryImpl();
- virtual ~GeometryFactoryImpl();
- public:
- virtual Geometry* CreateGeometry();
- };
- #endif
此時的目錄結構爲:
include 存放.h文件
src 存放.cpp文件
四、編寫makefile,編譯動態庫
- OBJS=GeometryFactoryImpl.o \
- GeometryImpl.o
- INCLUDE=-I../include
- TARGET=libgemt.so
- CPPFLAG=-shared -WI
- CC=g++
- LDLIB=
- $(TARGET) : $(OBJS)
- $(CC) $(CPPFLAG) $(INCLUDE) -o $(TARGET) $(OBJS) $(LDLIB)
- $(OBJS) : %.o : %.cpp
- $(CC) -c -fPIC $(INCLUDE) $< -o $@
- clean:
- -rm -f $(OBJS)
- install:
- cp $(TARGET) /usr/lib
將makefile文件放到src目錄下,而後進入src目錄,執行make命令,編譯so庫。
#make
編譯完成後將生成libgemt.so動態庫。
這個C++庫用到了C++裏面的虛基類,純虛函數,繼承,C函數,靜態變量等概念。下面就看一下SWIG如何將這個C++的so庫轉換爲Java接口。
2、利用SWIG將C++接口轉換爲Java接口
一、SWIG接口文件(.i)
SWIG須要編寫一個後綴爲.i的接口文件,把C++接口的定義寫在.i文件中,也能夠將C++的頭文件include到.i文件中。這裏咱們將C++接口文件GeometryAPI.h include到.i文件中,文件名爲gemt4j.i。
- /* File : gemt4j.i */
- %module gemt4j
- %{
- #include "GeometryAPI.h"
- %}
- %include "GeometryAPI.h"
module是模塊名。SWIG將C函數經過Java的JNI轉換爲JAVA方法,這些方法都以靜態方法的方式封裝到一個與模塊名同名的Java類中。
新建一個swig文件夾,將gemt4j.i文件存放到swig文件夾中。此時的目錄結構爲:
一、生成java類和wrap文件
編寫好.i文件,就能夠用swig生成java類和C++接口的wrap文件。
執行一下命令
#swig -c++ -java -package com.test -outdir ./ -I../include gemt4j.i
swig參數說明:
1)-c++ -java
告訴swig將C++接口轉換爲java接口。若是是將C接口轉換爲java接口,就不須要-c++,直接寫 swig -java就能夠。
2)-package
生成的java類的包的名稱
3) -I
gemt4j.i中include的.h文件的路徑
4)gemt4j.i
swig的.i文件
執行這條命令後,將在swig路徑下生成幾個文件
1)gemt4j_wrap.cxx
C++文件,包裝器文件。它將C++類的方法轉換爲C的函數。
2)gemt4j.java
這是與剛纔定義的module同名的一個類。
3)gemt4jJNI.java
打開這個文件能夠看到,C++類的方法都轉化爲Java的靜態方法。
4)其餘與C++類同名的Java類
每個C++類都被轉化爲與之對應的Java類,而且類名,方法明徹底同樣。
二、編譯gemt4j_wrap.cxx文件爲so庫
1) java頭文件
編譯gemt4j_wrap.cxx須要用到jni的頭文件jni.h
在個人機器上jdk安裝在/opt/jdk1.5.0_20/下,
須要包行兩個路徑:
1)/opt/jdk1.5.0_20/include/
2) /opt/jdk1.5.0_20/include/linux/
2) libgemt.so庫
還須要連接剛纔編譯好的libgemt.so庫
編寫makefile文件
- OBJS=gemt4j_wrap.o
- INCLUDE=-I../include \
- -I/opt/jdk1.5.0_20/include \
- -I/opt/jdk1.5.0_20/include/linux
- TARGET=libgemt4j.so
- CPPFLAG=-shared -WI
- CC=g++
- LDLIB=-lgemt
- $(TARGET) : $(OBJS)
- $(CC) $(CPPFLAG) $(INCLUDE) -o $(TARGET) $(OBJS) $(LDLIB)
- $(OBJS) : %.o : %.cxx
- $(CC) -c -fPIC $(INCLUDE) $< -o $@
- clean:
- -rm -f $(OBJS)
- install:
- cp $(TARGET) /usr/lib
生成libgemt4j.so庫,jni就是經過這個庫調用libgemt.so庫中的類和方法的。
到如今爲止,就經過SWIG將C++接口轉換爲Java接口。
3、使用SWIG生成的Java接口
一、編譯Java文件
進入swig目錄,SWIG生成的Java文件如今都在這裏。
#javac *.java
生成class文件。
剛纔咱們設定的java包是com.test
建立com/test目錄,將class文件移動到com/test目錄下,而後打包
#cd swig
#tar -cvf gemt4j.jar ./com
生成gemt4j.jar包
二、將libgemt4j.so放到java的library path路徑下。
能夠經過下面的方式查一下java的library path路徑
- class test{
- public static void main(String[] argv){
- System.out.println(System.getProperty("java.library.path"));
- }
- }
我這裏的library pah爲:/opt/jdk1.5.0_20/jre/lib/i386
把libgemt4j.so放到這個路徑下便可。
三、編寫java代碼。
- import com.test.*;
- class test{
- static {
- System.loadLibrary("gemt4j");
- }
- public static void main(String argv[]){
- GeometryFactory factory = null;
- factory = gemt4j.meGetGeometryFactoryInstance();
- if(factory==null){
- System.out.println("null GeometryFactory");
- return;
- }
- Geometry geometry = null;
- geometry = factory.CreateGeometry();
- if(geometry==null){
- System.out.println("null geometry");
- return;
- }
- System.out.println(geometry.GetType());
- geometry.Release();
- }
- }
說明:
System.loadLibrary("gemt4j");
用於裝載libgemt4j.so庫。
其餘代碼與普通的java無異。
編譯java文件:
#javac -cp /home/hawk/code/swig/dll/java/gemt4j.jar test.java
執行test程序
#java -cp /home/hawk/code/swig/dll/java/gemt4j.jar:/home/hawk/code/swig/dll/java test
輸出結果爲:
GeometryImpl
能夠看出,實現了Java調用C++類庫libgemt.so