用Swig将c/c++程序转为java代码(使用swig实现java调用cc++的方法)

Posted 阿冬专栏

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用Swig将c/c++程序转为java代码(使用swig实现java调用cc++的方法)相关的知识,希望对你有一定的参考价值。

用Swig将c/c++程序转为java代码


个人声明,源自: mazhenyu
 邮箱:malin213@tom.com VC++ .net OpenGL QQ:274955617

在windows下使用SWIG的环境配置问题(将c/c++转为java语言)
在Windows下安装:
SWIG的安装不同于一般的Windows安装程序,它相对而言更加容易上手。主要的步骤如下:
1.从SWIG网站下载swigwin压缩包然后解压缩到一个目录。这就是我们下载Windows平台下的版本的所有事情。
2.像Swig Windows 例子部分描述的设置环境变量来用Visual C++运行案例.

 Java下环境变量的设置: 
 JAVA_INCLUDE : Set this to the directory containing jni.h
 JAVA_BIN : Set this to the bin directory containing javac.exe

 Example using JDK1.3:
 JAVA_INCLUDE: d:\\jdk1.3\\include
 JAVA_BIN: d:\\jdk1.3\\bin
在win2000系统的环境参数中添加两个新的变量JAVA_INCLUDE和AVA_BIN,值分别为
d:\\jdk1.3\\include和d:\\jdk1.3\\bin。即对应的java的安装目录
//
SWIG对c/c++中对象和类型的支持?
ANSI C (标准C)
SWIG能够打包封装的标准C对象包括:
1.所有标准C数据类型 
2.全局函数,全局变量,和常量
3.结构体和联合体 
4.指针
5.数组和多维数组
6.指针函数 
7.可变长度的参数. 
8.类型定义Typedef 
9.枚举Enums

ANSI C++ (标准C++)
SWIG提供对几乎所有标准C++对象的封装:
1.所有C++数据类型
2.参数 
3.成员指针 
4.类 
5.继承和多重继承 
6.重载函数和方法(使用动态接口)
7.重载操作
8.静态成员
9.命名空间(包括使用声明,别名,嵌套,等)
10.模板
11.成员模板
12.特殊模板和部分特殊应用
13.Smart指针
14.支持strings,STL vector等的库

The only major C++ feature not currently supported by SWIG is the wrapping of nested classes--a problem we're working on. SWIG also does not allow C++ virtual methods to be implemented in certain target languages (a subtle feature that might be useful in projects that rely heavily on the use of callback functions). 
C++ users who rely on advanced template programming techniques (e.g., template meta-programming) should also be aware that SWIG currently requires manual instantiation of all template classes. Therefore, if your application somehow involves the instantiation of 50000 template classes, your mileage might vary.


SWIG输入数据格式:
在输入上,SWIG需要包括C/C++声明和特殊的SWIG指示的一个文件。大部分来说, 这是一个特殊的SWIG
接口文件通常是特指.i或.swg的文件格式。在特殊的情况下,SWIG能直接被用于原始的头文件或源文件。
但是,这并不是最通常的典型使用案例而且会有几种原因使你不会想这样做(原因在后面会讲述)。

最通常的SWIG接口文件格式如下:

%module mymodule 
%
#include "myheader.h"
%
// Now list ANSI C/C++ declarations
int foo;
int bar(int x);
...

模块名由指定的%module来给出(或者用-module命令行选项).这段指示性文字必须写在文件的头部并且
在使用时将这个模块名作为扩展模块对象来使用(此外,这个模块名经常在目标语言中被定义成一个命
名空间来使用)。如果模块名在命令行已经被给出了,系统将不考虑由%module标示的模块名了。

所有在%...%块内的东西将被简单作为结果逐字拷贝到SWIG创建的wrapper(包装)文件中。这部分大部分
被用来包括头文件和生成wrapper代码需要的其它声明。这里很重要的强调一点因为你在一个SWIG的输入
文件中包含了一个声明,这个声明并不自动显示在生成的wrapper代码中———因此你需要确信你确实
把正确的头文件在% ... %部分中。这里应该指出SWIG不解析和解释附在% ... %部分的文字。SWIG的
%...%内的语法和语义很类似于输入文件中的声明部分???

/
SWIG使用说明
 1.编写interface文件example.i
     如果api有头文件就更简单了,下面的代码定义一个example类
   
 example.i文件 
 %module example
 %
 #include "example.h"
 %

 %include "example.h"

    2.  swig -java example.i  
     生成符合JNI语法(见上)的C文件: example_wrap.c
     生成Java类文件:exampleJNI.java,example.java
 swig -c++ -java example.i
 同时生成example_wrap.c 文件

    3.VC把example_wrap.c 和example.c 打包成dll.

    4.在普通java程序里使用example.java
 

      System.loadLibrary("example");
      int g = new Example().add(42,105);

 

//
STL/C++库的转化
这一部分的库模块提供访问部分标准C++库包括STL的方法。使SWIG支持STL还是一个正在努力中的事情。
SWIG对于一些语言模块的支持使较全面的但是对很少用到的库则支持的很少。
下面就是表示了C++类和支持的C++库 以及SWIG接口文件的对应表
C++ class    C++ Library file     SWIG Interface library file 
std::deque   deque    std_deque.i 
std::list    list    std_list.i 
std::map     map    std_map.i 
std::pair    utility   std_pair.i 
std::set     set    std_set.i 
std::string  string    std_string.i 
std::vector  vector    std_vector.i 
这个表应该说还没有很完善。一些语言模块支持上面的一个子集而另一些支持扩展的STL类.请仔细寻找
相关语言库目录下的库文件。

1.std_string.i

这个std_string.i库提供将C++ std::string对象转化为目标描述性语言的方法。举例:
(在example.i中)
%module example
%include "std_string.i"
std::string foo();
void        bar(const std::string &x);

在目标语言中:
x = foo();                # Returns a string object
bar("Hello World");       # Pass string as std::string

人们碰到的一个最常见的问题是在 类/结构 中包含一个 std::string。这个问题可以通过定义一个typemap来解决。
例如:
%module example
%include "std_string.i"

%apply const std::string& std::string* foo;

struct my_struct

  std::string foo;
;

在目标语言中:
x = my_struct();
x.foo="Hello World";      # assign with string
print x.foo;              # print as string
这个模块只支持std::string 和 const std::string &两种写法。指针和 非常量参数将被无修改的保留下来
并作为SWIG的指针返回。

库文件完全识别C++的命名空间。如果你输出std::string 或 将它重命名为另一种类型。请确认你将此重命名
声明包含到了你的接口文件中。例如:
%module example
%include "std_string.i"

using namespace std;
typedef std::string String;
...
void foo(string s, const String &t);     // std_string typemaps still applied

注:std_string库转换为Perl时在某些系统平台下出现不兼容性。我们正在查找原因。

-----------------------------------------------------------------------------------------------
2.std_vector.i
std_vector.i库提供了对C++ STL中的vector类的支持。使用此库通常包括使用%template 标识。你所需要做的
就是分清你要使用的vector中的数据类型。例如:
%module example
%include "std_vector.i"

namespace std
   %template(vectori) vector<int>;
   %template(vectord) vector<double>;
;

/
SWIG 对C++类继承的支持
SWIG支持单继承,一般可以很好的将单继承的类转为java对象。对多继承支持的程度不太好,需要人工参与.i文件的修改,详细请查找资料。

/
SWIG封装包不支持以下的C++语法:
1.重载方法和重载函数。SWIG封装不知道如何解决同名冲突因此你必须给每一个同名重载方法一个替换的名称,具体方法
是用%name如下所示:
void foo(int a);  
%name(foo2) void foo(double a, double b);

2.重载操作???。并不完全支持。对此唯一的工作区是写一个帮助函数。例如:
%inline %
    Vector *vector_add(Vector *a, Vector *b)
          ... whatever ...
   
%

3.命名空间。不完全支持。直到SWIG2.0发布以前将不会得到支持。

//
在VC++6.0的.dsp工程设置文件中配置SWIG调用
举例说明:
1.首先在Project->Settings->Post-build step选项卡下
Post-build description文字框中输入Java compile post-build step
在下面的commands中添加
echo on
"%JAVA_BIN%\\javac" *.java
这两句话的意思是编译完后调用javac将当前编译路径下的所有.java文件编译成.class二进制文件。

2.然后用写字版打开.dsp文件
在文件的倒数第四行# Begin Source File后添加

SOURCE=.\\example.i   

#DEBUG版本情况下的设置
!IF  "$(CFG)" == "example - Win32 Debug"

# Begin Custom Build 开始客户方生成
InputPath=.\\example.i
InputName=example

"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
 echo In order to function correctly, please ensure the following environment variables are correctly set: 
 echo JAVA_INCLUDE: %JAVA_INCLUDE% 
 echo JAVA_BIN: %JAVA_BIN% 
 echo on 
 ..\\..\\..\\swig.exe -c++ -java $(InputPath) 
 
# End Custom Build 结束客户方生成

#RELEASE版本情况下的设置
!ELSEIF  "$(CFG)" == "example - Win32 Release"

# Begin Custom Build 开始客户方生成
#指定输入路径和输入名称
InputPath=.\\example.i
InputName=example

#调用swig -c++ -java生成对应的java文件(.java)
"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
 echo In order to function correctly, please ensure the following environment variables are correctly set: 
 echo JAVA_INCLUDE: %JAVA_INCLUDE% 
 echo JAVA_BIN: %JAVA_BIN% 
 echo on 
 ..\\..\\..\\swig.exe -c++ -java $(InputPath) 
 
# End Custom Build 结束客户方生成

以上是关于用Swig将c/c++程序转为java代码(使用swig实现java调用cc++的方法)的主要内容,如果未能解决你的问题,请参考以下文章

SWIG 的应用

使用 SWIG for Java,我如何有选择地 swig 巨大的 C/C++ 头文件的某些部分?

在 perl 中调试由 SWIG 包装的共享库

如何实现 C/C++ 与 Python 的通信

SWIG 之一:基础入门

SWIG (Java):如何将带有回调函数的结构从 Android 应用程序传递给 C++?