zoukankan      html  css  js  c++  java
  • 利用SWIG转换C++接口到Java接口

        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代码  收藏代码
    1. #ifndef __GEOMETRY_API_H__  
    2. #define __GEOMETRY_API_H__  
    3. //===========================================================================  
    4. class Geometry;  
    5. class GeometryFactory;  
    6.   
    7. //---------------------------------------------------------------------------  
    8. /*  
    9.  * 说明:几何对象类  
    10.  */  
    11. class Geometry  
    12. {  
    13. public:  
    14.         Geometry(){}  
    15.         virtual ~Geometry(){}  
    16. public:  
    17.         virtual const char* GetType() = 0;  
    18.         virtual void Release() = 0;  
    19. };  
    20. //---------------------------------------------------------------------------  
    21. /*  
    22.  * 说明:几何对象工厂类  
    23.  */  
    24. class GeometryFactory  
    25. {  
    26. public:  
    27.         GeometryFactory(){}  
    28.         virtual ~GeometryFactory(){}  
    29. public:  
    30.         virtual Geometry* CreateGeometry() = 0;  
    31. };  
    32. //---------------------------------------------------------------------------  
    33. /*  
    34.  * 说明:C函数,用于获取GeometryFactory类的一个实例  
    35.  */  
    36. extern "C"  
    37. {  
    38.         GeometryFactory* meGetGeometryFactoryInstance();  
    39. }  
    40. //===========================================================================  
    41. #endif  
    42.       

        2、Geometry接口的实现类GeometryImpl 
       
    C++ geoemtryimpl.h代码  收藏代码
    1. #ifndef __GEOMETRY_IMPL_H__  
    2. #define __GEOMETRY_IMPL_H__  
    3.   
    4. #include "GeometryAPI.h"  
    5.   
    6. class GeometryImpl : public Geometry  
    7. {  
    8. public:  
    9.         GeometryImpl();  
    10.         virtual ~GeometryImpl();  
    11. public:  
    12.         virtual const char* GetType();  
    13.         virtual void Release();  
    14. };  
    15. #endif  
    16.       

       
    C++ geoemtryimpl.cpp代码  收藏代码
    1. #include "GeometryImpl.h"  
    2.   
    3. GeometryImpl::GeometryImpl()  
    4. {  
    5. }  
    6. GeometryImpl::~GeometryImpl()  
    7. {  
    8. }  
    9. const char* GeometryImpl::GetType()  
    10. {  
    11.     return "GeometryImpl";  
    12. }  
    13. void GeometryImpl::Release()  
    14. {  
    15.     delete this;  
    16. }  
    17.       

        3、GeometryFactory接口的实现类GeometryFactoryImpl 
    C++ geometryfactoryimpl.h代码  收藏代码
    1. #ifndef __GEOMETRY_FACTORY_IMPL_H__  
    2. #define __GEOMETRY_FACTORY_IMPL_H__  
    3.   
    4. #include "GeometryAPI.h"  
    5.   
    6. class GeometryFactoryImpl : public GeometryFactory  
    7. {  
    8. public:  
    9.         GeometryFactoryImpl();  
    10.         virtual ~GeometryFactoryImpl();  
    11. public:  
    12.         virtual Geometry* CreateGeometry();  
    13. };  
    14. #endif  

        此时的目录结构为: 
            include     存放.h文件 
            src         存放.cpp文件 
        4、编写makefile,编译动态库 
    C++ makefile代码  收藏代码
    1. OBJS=GeometryFactoryImpl.o \  
    2.      GeometryImpl.o  
    3.   
    4. INCLUDE=-I../include   
    5. TARGET=libgemt.so  
    6. CPPFLAG=-shared -WI  
    7. CC=g++  
    8. LDLIB=  
    9.   
    10. $(TARGET) : $(OBJS)  
    11.     $(CC) $(CPPFLAG) $(INCLUDE) -o $(TARGET) $(OBJS) $(LDLIB)  
    12. $(OBJS) : %.o : %.cpp  
    13.     $(CC) -c -fPIC $(INCLUDE) $< -o $@  
    14. clean:  
    15.     -rm -f $(OBJS)  
    16. install:  
    17.     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代码  收藏代码
    1. /* File : gemt4j.i */  
    2. %module gemt4j  
    3. %{  
    4. #include "GeometryAPI.h"  
    5. %}  
    6. %include "GeometryAPI.h"  
    7.         

        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代码  收藏代码
    1. OBJS=gemt4j_wrap.o  
    2. INCLUDE=-I../include \  
    3.      -I/opt/jdk1.5.0_20/include \  
    4.      -I/opt/jdk1.5.0_20/include/linux  
    5. TARGET=libgemt4j.so  
    6. CPPFLAG=-shared -WI  
    7. CC=g++  
    8. LDLIB=-lgemt  
    9. $(TARGET) : $(OBJS)  
    10.     $(CC) $(CPPFLAG) $(INCLUDE) -o $(TARGET) $(OBJS) $(LDLIB)  
    11. $(OBJS) : %.o : %.cxx  
    12.     $(CC) -c -fPIC $(INCLUDE) $< -o $@  
    13. clean:  
    14.     -rm -f $(OBJS)  
    15. install:  
    16.     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代码  收藏代码
    1. class test{  
    2.     public static void main(String[] argv){  
    3.         System.out.println(System.getProperty("java.library.path"));  
    4.     }  
    5. }  

            我这里的library pah为:/opt/jdk1.5.0_20/jre/lib/i386 
            把libgemt4j.so放到这个路径下即可。 
         3、编写java代码。 
           
    Java代码  收藏代码
    1. import com.test.*;  
    2.   
    3. class test{  
    4.     static {  
    5.         System.loadLibrary("gemt4j");  
    6.     }  
    7.   
    8.     public static void main(String argv[]){  
    9.         GeometryFactory factory = null;  
    10.         factory = gemt4j.meGetGeometryFactoryInstance();  
    11.         if(factory==null){  
    12.             System.out.println("null GeometryFactory");  
    13.             return;  
    14.         }  
    15.         Geometry geometry = null;  
    16.         geometry = factory.CreateGeometry();  
    17.         if(geometry==null){  
    18.             System.out.println("null geometry");  
    19.             return;  
    20.         }  
    21.         System.out.println(geometry.GetType());  
    22.         geometry.Release();       
    23.     }  
    24. }  

            说明: 
                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 
  • 相关阅读:
    查询集 QuerySet
    JWT的认识和session的区别
    Django REST framework 简介
    Django自动获取项目中的全部URL
    flask数据库迁移
    类中方法的两种调用方式
    flask项目配置
    NOIP 模拟 $19; m u$
    NOIP 模拟 $18; m 老司机的狂欢$
    NOIP 模拟 $18; m 炼金术士的疑惑$
  • 原文地址:https://www.cnblogs.com/pandans/p/2007544.html
Copyright © 2011-2022 走看看