2012年9月6日 星期四

perl xs及swig初探

XS

  1. XS是用來供為perl呼叫C函式(反之亦可)的介面,可建立程式庫供動態載入或靜態連結;此一介面的描述語言,我們稱為"XS語言"。
  2. XSUB是XS介面的基本單位,其中sub即為subroutine(副程式)之縮寫。
  3. xsubpp是"XS語言"的編譯器,將"XS語言"編譯為C語言的函數定義,以做為perl及C之間呼叫函數的橋樑。
  4. 這黏著劑一般的程式碼,對參數及傳回值在背景進行轉換,參數可以傳值或傳址方式被修改。
  5. 為了簡化流程,我們可以用"XS語言"來撰寫介面,然後以xsubpp編譯之。"XS語言"讓我們可以表達在perl及C當中副程式被呼叫的"簽名"的對應。兩這兩者的型態一樣時,還有一種叫做h2xs的工具程式,用來將整個標頭檔(*.h)對應為"XS語言"檔。
  6. 在"XS語言"中,typemaps指令用來描述如何將C函式的參數和傳回直轉換為perl型態,反之亦然。perl本身帶有的預設typemap,可以處理常見的C型態,但是除此之外的typemap仍然需要手動撰寫。
  7. XS格式的檔案,一開始是一個C語言的節段,直到出現第一個MODULE=指令為止;之後則可以是其它的XS指令或是XSUB定義,這裏使用的語言就是之前曾經提到過的"XS語言"。

swig

Dave Beazley's SWIG可能提供了更方便的機制,請造訪 http://www.swig.org/ ,至於中文版可參考 http://www.swig.org/translations/chinese/index.html

在進行利用swig產生標頭之前,先來稍微了解一下流程,參考 SWIG (Simplified Wrapper and Interface Generator)

why

在幾個以國數字為標題的項目中,我們感興趣的是一及二。一的部分就是單純只有C檔,然後為它撰寫 i 檔。這個做法當然不像是一個好主意,至少通常現在的函式庫中都寫好了 h 檔。因此二的部分就是單純利用此 h 檔,產生 wrapper ,將它與函式庫一起編譯為 so 檔。要注意的是此 so 檔必需要在程式執行前先行手動載入。(此外五中使用了標準函式庫,其作法也值得參考一下。)不過即然可以直接由 h 檔產生介面,那為何還要手寫 i 檔呢?答案就在官方文件中~~

先來研究一下官方的文件。在抓下來的swig解開後,swig-2.0.8/Doc/Manual/Sections.html#Sections 有文件的目錄,16章以前講的是一般性的東西,17章以後針對個別的語言講解,其中perl的部分在第31章。第五章是官方建議必讀,像為何要另外撰寫 i 檔,答案在 5.7.4 中。第一個原因就是控制 scope,很多函數沒有必要去呈現成為介面,而且全部都產生介面的話會形成無用的巨大檔案;因此, i 檔可以提供精確的控制、組織;另一方面,swig有它的局限性,無法轉譯的介面,仍然需要在 i 檔中予以處理;最後,它本身就可以做為一個文件,使用者不必去挖 h 檔裏面的資訊,就可以了解如何使用介面。

how

接下來看看怎麼進行。5.7.1講解流程:
  1. (從 h 檔中)找出所要包裝的函數(和 h 檔)
  2. 建立 i 檔
  3. (從 h 檔中)複製函數宣告到 i 檔中,或使用 %include指令處理整個 h 或 c 檔
  4. 確認語法合於ANSI
  5. 如果不是直接引入 h 檔,請確認宣告的型態順序正確,以使介面可以順利編譯
  6. 將main()函數改名(但函式庫中應該不會有這個函數)
  7. 執行swig並編譯
官方文件在 swig-2.0.8/Doc/Manual/Perl5.html#Perl5_nn3 ,31.2節首先說明最簡單的情況,i 檔被 swig 編譯後會產生 c 檔(包含 i 檔中對應的宣告,應在此檔提供定義)及 pm 檔(包含載入模組的 perl 程式),要建置模組就必需將 c 檔編譯並連結到程式(我想它說的是31.2.2~4節所言,連結到perl);linking 有兩種,一種是動態,一種是靜態(不建議);31.2.2及31.2.3講的是編譯動態連結程式庫,前者使用gcc(不建議),後者使用Makemaker(建議使用)。31.2.2看一下可以了解連結的基礎,概念和一般win平台上dll的編譯其實是一樣的,要注意shared object 的名稱需同於module,並且至少要用gcc編譯swig產生的 *_wrap.c 檔;31.2.3則稍微說明一下Makemaker的用法,注意這裏提供的參數與上節的對應,另外在 http://gdwang.blogspot.tw/2011/09/linux-how-to-write-perl-extension-use.html 有給出比較實際的語法,而且所連結的成員通常是會包含程式庫沒錯,步驟上就是呼叫swig,用gcc編譯swig產生的 *_wrap.c 檔,寫Makefile.PL,執行perl Makerfile.PL,make,make install。31.2.5後半講到連結so的可能問題,算是這個架構的收尾。

PDF中的索引和書籤(二)

從 poppler-0.20.3\glib\poppler-page.cc 來看, poppler_page_get_link_mapping 這個函數是將所給定的頁面中的 Annots (似乎很確定就是Links) 走過一遍,然後回傳。

另一方面,從該檔的標頭檔看來,與cairo有很深的糾葛,或許是glib本來就是負責繪圖的部份使然。

在使用google 查詢 getAnnots()時,發現另外有個 Ruby 的專案 origami-pdf 也能parse pdf檔,不過看起來比較沒有在更新,而且個人猜測是單純對poppler作複製而已。

poppler-0.20.3\qt4\demos\toc.cpp 中似乎透露著更多顯示 TOC (table of contents) 的更多細節。其中定義了此一靜態函數 static void fillToc(...) ,是一個明顯的遞迴呼叫,同時對外它也被void TocDock::fillInfo() 呼叫,其中比較令人在意的是這行敘述

const QDomDocument *toc = document()->toc();

其定義應來自於 poppler-0.20.3\qt4\src\poppler-qt4.h

    class POPPLER_QT4_EXPORT Document {
...
QDomDocument *toc() const;

然後其定義依序又呼叫了 getOutline() ,

poppler-0.20.3\poppler\PDFDoc.cc(1466): Outline *PDFDoc::getOutline(){
poppler-0.20.3\poppler\PDFDoc.cc(1470):     outline = new Outline(catalog->getOutline(), xref);

看看 getOutline() 的定義 @poppler-0.20.3\poppler\Catalog.cc(827):

Object *Catalog::getOutline()
{
  if (outline.isNone())
  {
     Object catDict;

     xref->getCatalog(&catDict);
     if (catDict.isDict()) {
       catDict.dictLookup("Outlines", &outline);
     } else {
       error(errSyntaxError, -1, "Catalog object is wrong type ({0:s})", catDict.getTypeName());
       outline.initNull();
     }
     catDict.free();
  }
  return &outline;
}
大意是說,從xref(p-67)中取得catalog(p-77),存入catDict,找出其中的  Outlines(96) 並回傳之

結論就是,我們主要需要改寫的地方就是 static void fillToc(...) ,頂多再加上 void TocDock::fillInfo() 的小修改即可,為方便起見透過xs由perl來呼叫,這待下回分解

p.s.另外我也意外地發現 poppler-0.20.3\cpp\poppler-toc.h 中也定義了 toc(),但為 private
p.s.2.提及頁數的部分,均指"PDF 1.2 Reference Manual"

p.s.3. 原來已經有人用swig寫好了!!  http://search.cpan.org/~cornelius/Poppler-0.04/lib/Poppler.pm

2012年9月4日 星期二

在ubuntu上快速完成工作的小抄

有些快速鍵跟WIN32平台上差滿多,有必要整理一下

1.Mastering The Linux Shell – Bash Shortcuts Explained (Now With Cheat Sheets)
作者說他沒有全部放進去,我可是已經頭昏腦脹…光個shift+pgup/pgdn就非常有用了

2.Bash Shortcuts
還有連按兩次TAB的各種變化,真的是很威…

3.Bash command line shortcuts Cheat Sheet

精練多了,只是缺了shift+pgup/pgdn…這個其實滿有用的說

4.Bash Shortcuts For Maximum Productivity

高手級的,說真的很變態…

5.http://www.catonmat.net/
Bash One-Liners Explained, Part I: Working with files
Bash One-Liners Explained, Part II: Working with strings
Bash One-Liners Explained, Part III: All about redirections  該作者狂熱地研究並記錄者所有shell及script的用法,真是近兩年來的佳作。上面這幾篇來說,第三篇最重要;不過嚴格來說這三篇和shortcuts比較扯不上關係…

其它還有3篇

這篇要先會一點emacs才會有感覺,或許不是很重要的技巧,總之就是借用emacs的指令於bash中使用
這篇要先會一點vi才會有感覺,或許不是很重要的技巧,總之就是借用emacs的指令於bash中使用
這篇重要性高於前兩篇,當你一直按向上的箭頭要找出不知多久前下的一行指令,相信我,你會很需要把這篇附的cheatsheet找出來…

ps.剛在用firefox時不小心發現,把連結拖到在寫的blogger或是google docs文章是OK的!!這簡直太省事啦!!

ps1.有提到要改命令列提示符的話,請看  [分享]加快終端機下指令速度的方法

不過這件看來簡單的小事,在ubuntu上要弄到好,其實也接近令人抓狂的程度了

重點是要知道去修改那個檔案

http://www.csie.nctu.edu.tw/~tsaiwn/course/introcs/history/linux/linux.tnc.edu.tw/techdoc/Bash-env.htm

看看這篇文章,可以了解在預設情況,ubuntu 12.04 lts 版本在使用者的目錄已經有bash_login檔了,所以一股腦的照網路上找到的文章去改.profile 只會讓自己懷疑自己的能力而已。尤其是去改~/.bashrc,套句流行語,“你很奇怪耶你” XD

提示及ls顏色暫時先這樣改了
export PS1='\[\033[1;33m\]\u\[\033[1;37m\]@\[\033[1;32m\]\h\[\033[1;37m\]:\[\033[1;31m\]\W \[\033[1;35m\][\A] \[\033[1;36m\]:\!:\#:\$ \[\033[0m\]'
alias la='ls -la --color=auto' #長目錄列表
alias ll='ls -alFGh --color=auto' #長目錄列表,目錄末端附加/符號,不列group
alias ld='ls -CFd --color=auto' #這是抄來的,其實不大清楚功能
alias l='ls -CF' #目錄末端附加/符號

# 有顏色的 man

export PAGER="`which less` -s"
export BROWSER="$PAGER"
export LESS_TERMCAP_mb=$'\E[01;34m'
export LESS_TERMCAP_md=$'\E[01;34m'
export LESS_TERMCAP_me=$'\E[0m'
export LESS_TERMCAP_se=$'\E[0m'
export LESS_TERMCAP_so=$'\E[01;44;33m'
export LESS_TERMCAP_ue=$'\E[0m'
export LESS_TERMCAP_us=$'\E[01;33m' 另外,bash script中的cd為何沒有作用呢? http://stackoverflow.com/questions/255414/why-doesnt-cd-work-in-a-bash-shell-script 答案是要設成alias

輸入法的部分我習慣用無蝦米,試過ibus, gcin,覺得還是這個最正常
https://sites.google.com/a/dayi4u.co.cc/da-yi-xing-lie-qing-song-shu-ru-fa/fu-xia-mi-shu-ru-fa

PDF中的索引和書籤(一)

在WIN7用adobe reader時,並不怎麼注意索引和書籤的分別;但是在ubuntu上發現可以自訂書籤,卻無法自訂索引後,回頭才發現WIN7不能自訂書籤,要在adobe acrobat上才可以(http://blog.yam.com/ebag/article/32389172)。這把我搞得一頭霧水啊…

由 http://blog.csdn.net/q465162770/article/details/5802151 該文初步可知,“/Type”中除了有“/Catalog(index 目录对象)”外,还有“/Outlines(bookmarks 书签大纲对象)”、“/Pages (页面组对象)”

再查 Portable Document Format Reference Manual (v 1.2) 看看,outline在94頁,catalog在75頁,還是不大懂啊…

http://ftp.gnome.org/pub/GNOME/sources/evince/3.5/?C=S;O=A
evince是ubuntu上開源的pdf viewer,抓下來看看源碼,發現在 ./po/zh_TW.po 裏有語言的轉換,看來開檔的動作主要在函式 ev_window_open_uri 當中執行,索引側欄定義在 ev-sidebar-links.c 中,bookmark側欄定義在 ev-sidebar-bookmarks.c 中,

由函式中稱為metadata的資料似乎對應到bookmarks來看,metadata應該是存在本機某個資料夾的資料,因此bookmarks並不是直接存到pdf檔中。

函式 ev_job_load_new 依序被呼叫。EV_TYPE_SIDEBAR_PAGE 是側欄的父類別,衍生出來的類別會以下列敘述宣告
./shell/ev-sidebar-attachments.c:                        G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,
./shell/ev-sidebar-layers.c:                        G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,
./shell/ev-sidebar-links.c:                        G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,
./shell/ev-sidebar-annotations.c:                        G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,
./shell/ev-sidebar-bookmarks.c:                        G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,
./shell/ev-sidebar-thumbnails.c:                        G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,

_EvDocumentLinksInterface 是做為 virtual table, 模擬 c++ virtual functions. In ev-poppler.cc:

iface->get_links = pdf_document_links_get_links;

是實際填上這個vtbl的地方,此函數中呼叫 poppler_page_get_link_mapping 來取得 mapping_list ,然後此函數離開了evince 的部分,進入 poppler 函式庫。

剛好在這時發現,poppler下的glib/demo目錄似乎有範例程式,且其中的links.c亦呼叫了 poppler_page_get_link_mapping ,似乎可以好好研究一下。又在ubuntu下建立的書籤,到底是存在那呢?應該比較修改前後PDF檔的大小即可判斷。比較結果確定書籤是存在其它地方,而ubuntu上顯示為“索引”的資料在WIN7則顯示為“書籤”。總之這又是一個命名不一致而產生的誤會。

2012年9月1日 星期六

Siri技術解析

可以看一下這篇文章http://itseer.blogspot.tw/2012/04/siri.html

不知道裏面有沒有用到stanford parser呢?

跟google的semantic web的關係,可以看這篇
http://mmdays.com/2011/11/11/would-siri-become-google-threat/

要救HTC,先做一套出來再說吧(當然你可以說那是google的事)

話說今年3月曾經有人做出土炮版siri,HTC是不是應該趕快去三顧茅蘆一下?

"An Introduction to Language Processing with Perl and Prolog"
331頁, 12.9 "Augmenting the Database and Answering Questions"
裏面說明了很多nlp在回答問題上的處理方式,也滿值得一看的

有空的話,比如說多兩個月的暑假,還想把下列的論文翻上一翻
自然语言处理主流会议近年最佳论文列表  
100 NLP Papers

Stanford Chinese Segmenter初探(二)

關於簡繁互轉的工具

http://sptuner.blogspot.tw/2012/08/convertz-v802.html 只適用win平台下,big5/gbk/unicode/utf-8/jis/shift-jis/euc-jp各種內碼之間自由轉換

http://search.cpan.org/~audreyt/Encode-HanConvert-0.35/lib/Encode/HanConvert.pm 提到以下三種方式

# iconv | b2g | iconv
# Encode::HanConvert b2g.pl -u
# Lingua::ZH::HanConvert trad2simp

再來還有cconv及opencc
根據 http://www.byvoid.com/application/opencc/ 的說法,opencc目前是最佳解了
官網在此: http://code.google.com/p/opencc/

ps.路上經過一個大陸的corpus 網站 http://www.corpus4u.org/forum/index.php  ,滿有趣的