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

27 篇文章 1 订阅


    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 


from : http://yingchao.iteye.com/blog/625797



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: SWIG是一个用于连接C/C++和其他编程语言的工具。它提供了一种简单的方式,可以通过自动生成中间代码来实现C/C++的功能与其他编程语言(如Java)之间的交互。 通过SWIG,我们可以将C代码转换Java代码,并在Java中调用C库中的函数。这样做的好处是可以利用C/C++的高性能、底层控制和已有的库文件,并在Java中使用这些功能。 要将C代码转换Java代码,我们需要这样做的步骤: 1. 创建一个SWIG接口文件,以描述C函数的输入和输出类型。这个接口文件使用SWIG定义的特定语法。 2. 使用SWIG运行器,将接口文件作为输入,并生成一个Java包含C函数的Java接口文件。 3. 创建Java代码,以断开连接的方式调用生成的Java接口文件中的C函数。 SWIG通过将C代码封装在JNI(Java Native Interface)调用中来实现C与Java的交互。这允许Java代码直接调用C代码,并从C代码中返回结果。 使用SWIG进行C到Java转换可以使开发人员更加方便地利用两种语言的优点,提高开发效率和性能。SWIG还支持其他编程语言,如Python、Ruby和Perl,使C代码更容易与这些语言进行交互。 总之,SWIG是一个非常有用的工具,可以帮助在C/C++Java之间实现无缝的交互,为开发人员提供了更多的灵活性和选择,并最大程度地利用现有的代码和库文件。 ### 回答2: Swig是一个开源工具,用于将C/C++代码转换为支持多种编程语言的代码,包括Java。使用Swig可以很方便地将C代码转换Java代码。 转换C代码为Java需经过以下步骤: 1. 安装Swig:首先需要安装Swig工具,可以从Swig官方网站下载并按照指示进行安装。 2. 编写接口文件:接口文件是一个后缀名为.i的文件,用于定义需要转换的C代码和Java代码的映射关系。在接口文件中,需要指定需要转换的C函数的签名以及导出到Java的类、方法、成员变量等。 3. 生成包装代码:使用Swig生成器来生成C和Java代码的包装代码。通过运行类似以下命令来生成包装代码: ``` swig -java your_interface.i ``` 4. 编译和构建:在生成的C代码中,使用Java Native Interface(JNI)来与Java代码进行交互。使用C/C++编译器将C代码编译为共享库(.so或.dll文件),以供Java程序调用。 5. 构建Java代码:创建Java项目,在项目中引入包装代码并实现调用。可以使用JNI函数调用C函数,或直接使用包装代码生成的Java类和方法进行调用。 需要注意的是,转换C代码到Java并不是一种直接的转换过程,可能存在一些依赖问题,对于一些复杂的C代码或使用了C特定功能的代码,还需要在Java代码中添加适当的兼容性处理。 总结而言,Swig是一个强大的工具,可以将C代码转换Java代码,简化了C/C++Java之间的交互过程,提高了代码的可维护性和可扩展性。 ### 回答3: SWIG(Simplified Wrapper and Interface Generator)是一个用于将C/C++代码转换为其他语言的工具。如果想要将C代码转换Java代码,可以使用SWIG来完成。 首先,在使用SWIG之前,需要确保已经安装好了SWIG,并且配置好了相关的环境变量。 接下来,需要创建一个包含C代码的接口文件,该文件的后缀名通常为.i。在接口文件中,需要使用SWIG的语法来指定要转换的C函数和类型。 然后,使用SWIG命令对接口文件进行处理,以生成Java代码。命令的语法通常为:swig -java interfacefile.i 完成上述操作后,会生成一系列的Java文件,包括接口文件中指定的函数和类型的Java封装类。 最后,可以将生成的Java代码导入到你的项目中,并与其它Java代码一起进行编译和运行。 需要注意的是,SWIG并非完美的工具,可能会有一些限制和问题。在使用SWIG进行CJava时,可能会遇到一些类型对应的困难,或者在C和Java之间的内存管理方面的差异。因此,在使用SWIG转换代码时,需要谨慎处理这些问题,并进行相应的修改和调试。 总之,通过使用SWIG,我们可以方便地将C代码转换Java代码,从而能够在Java平台上使用C语言的功能和库。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值