(原文來自: 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
運行及測試結果:
源代碼可以從這里下載: