(原文来自: 2006-06-18 尝试了一下用 swig 编写 JNI 程序)

总是觉得编写 JNI (Java Native Interface) 程序是件复杂的事情, 于是开始漫无目的地搜索是否有简单一点的方法, 倒是有些商业软件提供这样的功能, 比如 http://www.jniwrapper.com 就提供了通过 Java 直接调用 DLL 的功能(可惜是商业软件, 哈哈).

搜索中无意到了 swig 的网站( http://www.swig.org ), 看到一个用 swig 产生 Java 模块的例子(原来知道 swig 是因为 python 的缘故), 于是就照着例子自己尝试了一下(比例子稍微复杂一点, 另外我是用 mingw 上的 gcc 进行编译的).

源代码包括 3 个文件, Example.c, Example.i, net/thinkbase/test/Test.java:

/** Example.c ****************************************************************/
#include <time.h>

/**A variable*/
double  PI =  3.1415927 ;

/**Return n!*/
int  fact ( int  n ) {
     if  ( n <=  1 )
         return  1 ;
     else
         return  n*fact ( n- 1 ) ;
}

/**mod function*/
int  mod ( int  x,  int  y ) {
     return  ( x%y ) ;
}

/**Get time as String*/
char  * getTime (){
     time_t ltime;
     time ( &ltime ) ;
     return  ctime ( &ltime ) ;
}

/**to upper case*/
char  * toUpperCase ( char  * result ){
     char  * p = result;
     while ( '\0' !=*p ){
         char  c = *p;
         if  ( ( c >  'a' ) && ( c <  'x' ) ){
         *p = c- 32 ;
         }
         p++;
     }
     return  result;
}


/** Example.i ****************************************************************/
%module Example
% {
     /* Put header files here or function declarations like below */
     extern  double  PI;
     extern  int  fact ( int  n ) ;
     extern  int  mod ( int  x,  int  y ) ;
     extern  char  * getTime () ;
     extern  char  * toUpperCase ( char  * str ) ;
% }

extern  double  PI;
extern  int  fact ( int  n ) ;
extern  int  mod ( int  x,  int  y ) ;
extern  char  * getTime () ;
extern  char  * toUpperCase ( char  * str ) ;


/** net/thinkbase/test/Test.java *********************************************/
package  net.thinkbase.test;

import  net.thinkbase.test.swig.Example;

public class  Test  {
     public static  void  main ( String argv []) {
         System.loadLibrary ( "Example" ) ;
         System.out.println (
             "    Example.getPI()      = "  + Example.getPI ()) ;
         System.out.println (
             "    Example.fact(6)      = "  + Example.fact ( 6 )) ;

         System.loadLibrary ( "Example" ) ;
         System.out.println (
             "    Example.mod(100, 30) = "  + Example.mod ( 100 30 )) ;
         System.out.println (
             "    Example.getTime()    = "  + Example.getTime ()) ;
         System.out.println (
             "    Example.toUpperCase(\"Hello, world!\") = "  +
             Example.toUpperCase ( "Hello, world!" )) ;
     }
}



试验步骤

建立必要的目录:
  • mkdir "net/thinkbase/test/swig"
  • mkdir ".out"
使用 swig 建立相关接口:
  • swig -java -package net.thinkbase.test.swig -outdir net/thinkbase/test/swig Example.i
编译 c 文件得到 dll:
  • gcc -c Example.c -o .out/Example.o -I%JAVA_HOME%/include -I%JAVA_HOME%/include/win32
  • gcc -c Example_wrap.c -o .out/Example_wrap.o -I%JAVA_HOME%/include -I%JAVA_HOME%/include/win32
  • gcc -shared .out/Example.o .out/Example_wrap.o -mno-cygwin -Wl,--add-stdcall-alias -o .out/Example.dll
编译测试用的 Java 程序:
  • javac -sourcepath . net/thinkbase/test/Test.java -d .out
运行测试:
  • java -cp .out -Djava.library.path=.out net.thinkbase.test.Test
运行及测试结果:
源代码可以从这里下载: