2012年6月30日 星期六

我的電腦在潤秒


今天潤秒,由於潮汐力等導致地球自轉些微的不規律,與原子時鐘間產生誤差,故增潤秒來的校時

若你的電腦有裝 ntpd - Network Time Protocol (NTP) daemon 之類的軟體,
那麼在log上是看得到潤秒的痕跡的:

Jul  1 07:59:59 <我的電腦名稱> kernel: Clock: inserting leap second 23:59:60 UTC

基於與格林威治標準時的時差,故電腦在早上八點潤秒


今天是自1972年來第25次潤秒



關於潤秒的不錯文章:

http://big5.ce.cn/xwzx/shgj/gdxw/201206/29/t20120629_23448923.shtml
7月1日7時59分全球時間增1秒 閏秒去留引爭議

http://www.space.com/16356-leap-second-added-clocks-saturday.html
NASA explains why clocks will get an extra second on June 30

2012年6月27日 星期三

不曾璀燦的流星


眾人滿懷的希望  到來 意外的時間
諸神未貼實的星空 墜落 無聲無息

相信 未曾璀燦的流星
帶著原有的純淨
         昇華
            進入塵翅無法飛到的天堂

2012年6月3日 星期日

SWIG (Simplified Wrapper and Interface Generator)


SWIG (Simplified Wrapper and Interface Generator)
除能簡化 C/C++函式物件等在各語言間的使用,亦能達到相當程度的防駭功用
(因包裝後的程式碼已轉換,與原程式不同,故原碼即使有buffer overflow等弱點,轉換後弱點亦會消失)

swig預設輸出為當前目錄(i.e.相當於有一預設選項 -outcurrentdir),
可用 -outdir <目錄名> 或 -o [目錄名/]輸出wrap檔名 改變,
優先權為 -o  >  -outdir  >  -outcurrentdir

以 example.i , example.c 為例(其中example.i<自建>為example.c 的SWIG interface file)
example.c如下:
double  My_variable  = 3.0;

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

int my_mod(int n, int m) {
  return(n % m);
}

一.
建一example.i如下:(底下的%module後接自定模組名而%{...%}的作用如同yacc或bison的%{...%})
%module example
%{
/* Put headers and other declarations here */
extern double My_variable;
extern int fact(int n);
extern int my_mod(int n, int m);
%}

extern double My_variable;
extern int fact(int n);
extern int my_mod(int n, int m);

I. 在tcl中用其C函式:(如沒tcl.h須先安裝libtcl-devel之rpm)
step 1. swig -tcl example.i                     ;=> 產生能給tcl用的 example_wrap.c
step 2. g++ -shared -fpic example.c example_wrap.c -o example.so
上會產生example.so
之後,打tclsh進入tcl後:
% load ./example.so ;=> 載入 example.so
% fact 5 ;=> 120 (i.e. 5!)
% my_mod 26 7 ;=> 餘5
% expr $My_variable + 5.5 ;=> 3.0+5.5 = 8.5

II. 在perl中用其C函式:(如沒EXTERN.h須先安裝perl-devel之rpm)(底下perl版本5.12.3, 不同者自改step2.)
step 1. swig -perl5 example.i     ;=> 產生能給perl用的example_wrap.c與example.pm
step 2. g++ -shared -fpic example.c example_wrap.c -I/usr/lib/perl5/5.12.3/i386-linux-thread-multi/CORE -o example.so
上會產生example.so
之後,建perl之script如下:(執行結果同I.)
#!/usr/bin/perl
# 下行即載入上面於同目錄下所建之example.so
use example;
print example::fact(5), "\n";
print example::my_mod(26,7), "\n";
print $example::My_variable + 5.5, "\n";        ;因此處example::My_variable為變數,故加$

III. 在python中用其C函式: (底下python版本2.7, 不同者自改step2.)
step 1. swig -python example.i     ;=> 產生能給python用的example_wrap.c與example.py
step 2. g++ -shared -fpic example.c example_wrap.c -I/usr/include/python2.7 -o _example.so
上會產生 _example.so
之後,建python之script如下:(執行結果同I.)
#!/usr/bin/python
# 下行即載入上面於同目錄下所建之_example.so (可視module example為物件)
import example
print example.fact(5)
print example.my_mod(26,7)
print example.cvar.My_variable + 5.5


二.簡化法:
step 0. 把 example.i 減化如下:
%module example
%{
#include "example.h"
%}
%include "example.h"

I.在perl中用其C函式(header files): (底下的example.h內容與example.c一模一樣)
step 1. swig -perl5 example.i ;=> 產生能給perl用的example_wrap.c與example.pm
step 2. g++ -shared -fpic example.h example_wrap.c -I/usr/lib/perl5/5.12.3/i386-linux-thread-multi/CORE -o example.so
上會產生example.so 之後步驟同 一II.

II.在php中用其C函式 (如沒php-config須先安裝 php-devel)
step 1. swig -php example.i ;=> 產生能給php用的example.php  example_wrap.c  php_example.h 三個檔案
step 2. g++ `php-config --includes` -shared -fpic example_wrap.c -o example.so
其中step1.會產生給php用的 example.php  example_wrap.cpp php_example.h 三個檔案
而step2.會產生example.so
之後,建一php script如下:(如沒/usr/bin/php須先安裝php-cli)
<?php
include("example.php");
echo fact(5) . "\n";
echo my_mod(26,7) . "\n";
echo example::My_variable_get() + 5.5 . "\n";
?>

且尚須在當前目錄下建一php.ini檔如右(僅一行): extension=./example.so
然後執行:php --php-ini ./php.ini ./ex_php        執行結果同一.


三.cmake  (底下以python為例)
一目錄中除有與一同example.i, example.cxx(亦與上述之example.c一模一樣)外,
尚須建一CMakeLists.txt檔案如下:
# 只需稍改後面四行即可用於其他的python程式
# 例如若是與二同之example.i與example.h 則把底下的example.cxx改成example.h

FIND_PACKAGE(SWIG REQUIRED)
INCLUDE(${SWIG_USE_FILE})

FIND_PACKAGE(PythonLibs)
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})

INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})

SET(CMAKE_SWIG_FLAGS "")

SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES CPLUSPLUS ON)
SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES SWIG_FLAGS "-includeall")
SWIG_ADD_MODULE(example python example.i example.cxx)
SWIG_LINK_LIBRARIES(example ${PYTHON_LIBRARIES})

然後在此目錄下打: cmake .    (.表當前目錄)
其後再打:make
上會產生 _example.so  (若在Windows下會產生 _example.pyd)
其餘步驟同 一III.

四.c++ wrap (以python為例)(example.h與example.i同二.)(swig未完全支援c++,故預設為c)
(下面的step1產生能給python用的example.py與example_wrap.cpp<用-c++才可產生此.cpp,不然預設是.c>)
step 1. swig -c++ -python -o example_wrap.cpp example.i
step 2. g++ -shared -fpic example_wrap.cpp -I/usr/include/python2.7 -o _example.so
上會產生 _example.so 之後步驟同 一III.


五.於其他語言中使用C語言常用函式庫(以sin()與strcmp()為例)
建一檔example.h,把欲用到的函式其header files納進此檔,
由於我們這裡只用到sin()與strcmp(),故此處example.h內容只有下面兩行:
#include <math.h>
#include <strings.h>

而 example.i 如下:
%module example
%inline %{
#include "example.h"
extern double sin(double x);
extern int strcmp(const char *, const char *);
%}
#define PI 3.14159265359

I. 在tcl中用C函式:(如沒tcl.h須先安裝libtcl-devel之rpm)
step 1. swig -tcl example.i                     ;=> 產生能給tcl用的 example_wrap.c
step 2. g++ -shared -fpic example_wrap.c -o example.so
上會產生example.so
之後,打tclsh進入tcl後:
% load ./example.so ;=> 載入 example.so
% puts PI ;=> 輸出 3.14159265359
% sin [expr {$PI/2}] ;=> 輸出 1.0
% strcmp He He ;=> 輸出 0  (因兩字串相等)
% strcmp He She ;=> 輸出 -1 (因兩字串不相等)

II. 在python中用C函式: (底下python版本2.7, 不同者自改step2.)
step 1. swig -python example.i     ;=> 產生能給python用的example_wrap.c與example.py
step 2. g++ -shared -fpic example_wrap.c -I/usr/include/python2.7 -o _example.so
上會產生 _example.so
之後,建python之script如下:(執行結果同I.)
#!/usr/bin/python
# 下行即載入上面於同目錄下所建之 _example.so (可視module example為物件)
import example
print example.PI
print example.sin( example.PI / 2 )
print example.strcmp('He','He')
print example.strcmp('He','She')

III.在clisp中用C函式: (注意:step 2.可能因版本不同而需更改)
step 1. swig -clisp example.i     ;=> 產生能給clisp用的example.lisp
step 2. 在 example.lisp 中 的 (default-foreign-language :stdc) 之下增加一行:
        (setf +library-name+ "libstdc++.so.6")
        且為避免與clisp內建sin函數衝突,其下一行處之(ffi:def-call-out sin 的 sin 改成 sin2  
        然因(:name "sin") 保留沒更動,故仍以example:sin 方式呼叫之
之後,打clisp進入lisp後照以下進行,結果會同上:
(load "./example.lisp")
(print example:PI)
(example:sin (/ example:PI 2))        ;因clisp有內建PI, 故於此處...(/ PI 2)) 亦可
(example:strcmp "He" "He")
(example:strcmp "He" "She")


六.於其他語言中使用C++/C語言常用函式庫(以sin()與strcmp()為例)
example.h 與 example.i 同 五.

I.在Java中用C++/C函式: (注意:須先安裝java sdk, 而step 2.可能因java sdk版本不同而需更改)
下行會產生 exampleConstants.java  example.java  exampleJNI.java  example_wrap.cxx 四個檔案
step 1. swig -c++ -java example.i
step 2. g++ -shared -fpic example_wrap.cxx -I/usr/lib/jvm/java/include -I/usr/lib/jvm/java/include/linux -o example.so
上會產生 libexample.so
之後,建一java檔如下:(設檔名為runme.java)
public class runme {
  static {
    System.loadLibrary("example");
  }

  public static void main(String argv[]) {
    System.out.println(example.PI);
    System.out.println(example.sin(example.PI / 2));
    System.out.println(example.strcmp("He","He"));
    System.out.println(example.strcmp("He","She"));
  }
}

以 javac *.java 編譯成*.class後,再用 java runme 來執行,輸出結果同 五.

註:出現錯誤常是因為java.library.path中不含當前目錄,
    這時先export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH 後再跑java runme 即可


II.在Ruby中用C++/C函式:(如沒ruby.h須先安裝ruby-devel之rpm)(注意:step 2.可能因版本不同而需更改)
step 1. swig -c++ -ruby example.i           ;=> 產生能給Ruby用的 example_wrap.cxx
step 2. g++ -shared -fpic example_wrap.cxx -I/usr/lib/ruby/1.8/i586-linux/  -o example.so
上會產生example.so
之後,建一ruby程式檔如下:(執行結果同 五.)
#!/usr/bin/ruby -w
#下行即載入上面於同目錄下所建之example.so之module
require 'example'
puts Example::PI
puts Example.sin( Example::PI / 2 )
puts Example.strcmp('He','He')
puts Example.strcmp('He','She')


III.在Lua中用C++/C函式:(如沒lua.h等須先安裝liblua-devel之rpm)(注意:step 2.可能因版本不同而需更改)
step 1. swig -c++ -lua example.i           ;=> 產生能給Lua用的 example_wrap.cxx
step 2. g++ -shared -fpic example_wrap.cxx -o example.so
上會產生example.so
之後,建一lua程式檔如下:(執行結果同 五.)
#!/usr/bin/lua
-- 下行即載入上面於同目錄下所建之example.so之module
require "example"
print( example.PI )
print( example.sin( example.PI / 2) )
print( example.strcmp("He","He") )
print( example.strcmp("He","She") )


ref.
http://www.swig.org/tutorial.html
file:///usr/share/doc/swig/Manual/SWIGDocumentation.html
/usr/share/doc/swig-doc/Examples/ 中有不少其他語言的程式例