您的位置:首页 > 编程语言 > C语言/C++

利用SWIG转换C++接口到Java接口

2017-10-18 15:41 471 查看
    SWIG(Simplified Wrapper and Interface Generator)是一个将C/C++接口转换为其他语言接口的工具,从而可以讲C/C++的库集成到其他语言的系统中。目前SWIG已经可以支持Python, Java, C#,Ruby,PHP,R语言等十多种语言。 
    本文介绍一下在Liuux平台上如何将C++接口转换为Java接口。 
    一、首先先编写一个C++的动态库。 
    代码如下: 
    1、接口文件定一个。 
     C++没有像Java/C#一样的interface关键词,但是可以用虚基类来定义接口个,虚基类同样是只有定义,没有实现类,它的功能现放在继承类中实现。 
   

C++ geometryapi.h代码  


#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  

      

    2、Geometry接口的实现类GeometryImpl 
   

C++ geoemtryimpl.h代码  


#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  

      

   

C++ geoemtryimpl.cpp代码  


#include "GeometryImpl.h"  

  

GeometryImpl::GeometryImpl()  

{  

}  

GeometryImpl::~GeometryImpl()  

{  

}  

const char* GeometryImpl::GetType()  

{  

    return "GeometryImpl";  

}  

void GeometryImpl::Release()  

{  

    delete this;  

}  

      

    3、GeometryFactory接口的实现类GeometryFactoryImpl 

C++ geometryfactoryimpl.h代码  


#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文件 
    4、编写makefile,编译动态库 

C++ 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接口。 

   二、利用SWIG将C++接口转换为Java接口 
   1、SWIG接口文件(.i) 
      SWIG需要编写一个后缀为.i的接口文件,把C++接口的定义写在.i文件中,也可以将C++的头文件include到.i文件中。这里我们将C++接口文件GeometryAPI.h include到.i文件中,文件名为gemt4j.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文件夹中。此时的目录结构为: 
        

 
    1、生成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类,并且类名,方法明完全一样。 
    2、编译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文件 

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接口。 

三、使用SWIG生成的Java接口 
    1、编译Java文件 
        进入swig目录,SWIG生成的Java文件现在都在这里。 
        #javac *.java 
        生成class文件。 
        刚才我们设定的java包是com.test 
        创建com/test目录,将class文件移动到com/test目录下,然后打包 
        #cd swig 
        #tar -cvf gemt4j.jar ./com 
        生成gemt4j.jar包 
    2、将libgemt4j.so放到java的library path路径下。 
        可以通过下面的方式查一下java的library path路径 
       

Java代码  


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放到这个路径下即可。 
     3、编写java代码。 
       

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 

from : http://yingchao.iteye.com/blog/625797
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java c++ swig