天天看點

perl-編譯方法(轉)

perl-全面編譯(轉)

文章分類:綜合技術

資迅 論壇 教程 雜志 SNS 搜尋 

-

Linux教程

Linux

Linux程式設計

C/C++程式設計

 Python程式設計

 Perl程式設計

 PHP程式設計

 shell

 程式設計技術

 kernel

 html技術

 zope

 java/jsp

 discuz

 Linux寶庫 Linux教程 Linux Linux程式設計 Perl程式設計  

06/14 2008 Perl語言全面編譯 分類:Perl程式設計 | Linux  作者:Linux寶庫  來自:Linux教程  釋出時間:2008年06月14日 您是本文的第5640位讀者

-

本文來自:Linux教程 -- http://doc.linuxpk.com/3089.html

如有不明白之處,歡迎參加社群讨論

  簡

  述

  本文将詳細講述Perl的編譯方法,獻給所有熱愛、喜歡Perl的程式員們。

  Perl自從面世以來1.0版本到現今的5.6版本,一直都有編譯程式,主要因為國内的中文資料很少,大多數人不願意去看或者不懂得英文資料,所造成不知道器編譯方法。即使是很多Perl界高手也同樣有此類問題。Perl編譯方法五花八門,各種編譯方法都有其重要的意義和弱點。另一方面Perl編譯方法不能流行的原因是,本身Perl就是一個免費的東西,人們不希望Perl成為編譯的商品,但是在國内也是是以而拖累了Perl的發展步伐。但在此我不贊成也不推崇Perl程式的編譯,Perl編譯有小些局限性,但是仍然可以完成所有任務,想要達到良好的編譯效果,需要高超的程式設計技術和相關經驗,重要的是對OOP(面向對象的程式設計)的了解,将會使得你的Perl程式更加易于編譯,運作速度更快,相容性更廣等特性。

  以前我寫過Perl在可嵌入式技術方面技術文章。它的優勢和其它嵌入語言無法比拟的相容性,Perl不但擁有PHP的可嵌入HTML技術,也同樣支援用PerlScript寫ASP的。但是如果你希望你的程式可以編譯執行,那麼可嵌入式方法顯然是不可能的。我幾乎不用ePerl、 mod_perl等可嵌入式Perl

  HTML

  頁,但是我更不贊成很多人把HTML置入程式之中,這兩種方法都有其好處以及壞處。我推崇模闆方式的編寫方法,大家可能也用過模闆方式,可能認為它在頁面量處理方面有很多問題?但是,那些都是陳舊古老的方式,也是說明你并未精通Perl語言,采用模闆方式調入HTML頁是相當好的方法,幾乎可以達到所有可嵌入式技術的功效,也可以像HTML程式内置方式的靈活操縱性。我覺得程式員和HTML制作員是不同的,如果我們采用ePerl、PHP、ASP,那麼你就不是一個真正的程式員,那隻是HTML技術的伺服器處理部分罷了,真正的程式是程式本身,而不附帶任何其它特性。

  我認為好的教學文章,應該讓讀者充分了解内容,充分擴充層面。諸如編寫一個Httpd程式,有很多傳統的程式員根本不了解

  http的通訊協定,即使講了很多内容,但是仍然搞得半懂不懂。本文将會充分擴充層面,讓讀者了解更多的技術資料,而不必看完本文後又要去尋找關聯技術資料。同樣國内目前有很多技術性書籍,都是來自國外的譯本,但是很多譯者并非此技術專家,在翻譯的時候很多東西無法充分了解,帶來的時間上的障礙。我希望國内的程式設計專家能夠寫一些有用的技術文章和書籍,因為我看過很多國人自己寫的文章都容易了解和操作。但是問題在于都偏向與基礎教學,目前急切地需要有更深層次的技術資料。

  内容大綱:

  1)

  PerlApp和PerlSvc編譯方法

  New!

  Easy!

  2)

  Perl2Exe

  編譯方法

  3)

  PerlCC

  編譯方法

  4)

  PerlCC之Bytecode

  編譯解析法——Just

  Like

  Java

  Program!

  New!

  Cool!

  5)

  OOP面向對象的程式之為編譯而設計

  6)

  HTML模闆程式設計方式——真正的WEB程式(Program)

  Good!

  7)

  聯合編譯以及執行個體

  Advanced!

  說明:如何選擇閱讀以上内容是很重要的,以上内容并非适合各個階層的Perl程式員。PerlApp和PerlSvc适合在 Windows2000環境下程式設計初學者和一般的Perl程式設計人員,Perl2Exe适合在非Windows和Windows95/98/Me

  環境下程式設計初學者和一般的Perl程式設計人員。PerlCC适合與任何作業系統平台,但是操作複雜,适合于中級程式員和進階程式員開發大宗商業化軟體(公衆客戶)使用。ByteCode是一種新型的編譯方式,類似Java,它需要Perl解析器的支援,但是它是靈活性最高的編譯方式,适合中級程式員和進階程式員開發大宗商業化軟體(服務商)使用。如果你希望你可以編寫出一個出色的Perl編譯的程式,那麼你必須閱讀第4節,它将告訴你如何使用面向對象的程式設計技術來實作Perl編譯程式的高效良好的開發環境和模式。

  第一節

  PerlApp和PerlSvc編譯方法

  PerlApp和PerlSvc是ActiveState

  公司開發的,它屬于

  Active

  Perl

  Dev

  Kit(PDK)産品。本編譯方法隻适合于Windows2000上運作,其它系統均無法正常使用,編譯程式必須是标準Perl和ActivePerl。

  PDK下載下傳位址:http://ftp.tanshuai.net/pub/

  ftp://ftp.tanshuai.net/pub/

  PerlApp和PerlSvc,前者是标準的應用程式,後者是Windows2000的服務程式(類似與IIS,一開機就啟動的服務程式,而且無法中斷它的運作)。他們有兩種運作模式:依靠(Dependent)和獨立(Freestanding),“依靠”模式程式運作的系統上必須有Perl 解析器和相關子產品,這樣的程式相對較小;“獨立”模式,Perl解析器等相關子產品都會完全嵌入在程式之中,這樣的程式在任何Windows2000作業系統上都可以順利運作,而不需要額外的支援,但是程式相對較大。

  使用方法:

  标準使用方法(“依靠”模式):

  perlapp

  這樣程式就會建立一個以腳本名命名的可執行檔案

  “獨立”模式:

  perlapp(或者perlsvc)

  –f

  定義輸出可執行檔案名:

  perlapp(或者perlsvc)

  –e=tanshuai.exe

  test.pl

  它将會把test.pl檔案輸出的可執行檔案名改為“tanshuai.exe”。

  設定程式屬性:

  perlapp(或者perlsvc)

  -i=

  類表名

  目标項目

  Filenumber

  檔案号碼

  Productnumber

  産品号碼

  Productname

  産品名稱

  Legaltrademarks

  合法商标

  Filedescription

  檔案說明

  Originalfilename

  原檔案名

  Fileversion

  檔案版本

  Comments

  注解

  Productversion

  産品版本

  Companyname

  公司名稱

  Internalname

  内部名稱

  Legalcopyright

  版權

 ?≌飧鍪焙蛴行┤絲贍懿淮竺靼祝飧鍪歉墒裁從玫摹H绻阍嘈垂齏in32程式,那就會知道,它是Windows程式的版本說明(如圖1)。

  圖1

  Perl.exe檔案的版本說明

  名稱與數值用“;”分開。而且所有項目值都需小寫。

  清理PerlCtrl

  的DLL:

  perlapp(或者perlsvc)

  –c

  添加子產品:

  perl(或者perlsvc)

  –a=

  如:perlapp

  tanshuai.pl

  –a=IO:Socket;XML::Parser;Tanshuai::Http;MP3;

  這樣子產品IO:Socket,XML::Parser,Tanshuai::Http和MP3就被置入程式内。

  Perl圖形界面:

  perlapp(或者perlsvc)

  –g

  如果你的程式非指令行或者CGI,是T/K圖形界面的話,就需要采取這個指令。

  排除

  Perl56.dll:

  perlapp(或者perlsvc)

  –x

  Perl56.dll是PerlApp執行的關鍵,但是如果你不希望他和你的程式在一起,你可以把它排除,另行安置,但是主意,一定要保證它的存在否則就無法正确運作

  添加額外檔案:

  perlapp(或者perlsvc)

  –b=

  如果你希望在程式内部打開檔案,請使用這個指令。

  如:open(FILE,“./PerlAPP.TXT“);@FILE=;close(FILE);

  這樣就必須打開“PerlAPP.TXT“檔案,但是你如果把它置入程式,它将會在記憶體中打開。(無法寫入)

  報告嵌入子產品錯誤:

  perlapp(或者perlsvc)

  -r

  一些子產品無法嵌入,使用該指令可以得出相關資訊。

  輸出詳細資訊:

  perlapp(或者perlsvc)

  -v

  如:perlapp

  tanshuai.pl

  –v

  輸出:

  Using

  myScript.pl

  for

  script

  name

  Input

  script

  name:

  tanshuai.pl

  Output

  exe

  name:

  tanshuai.exe

  Exe

  Mode:

  Perl

  Dependent

  Creating

  dependent

  executable

  解釋:PerlApp

  和PerlSvc無法在Windows95/98/ME

  PerlApp使用的部分Win32

  API函數未被支援。

  第二節

  Perl2EXE

  編譯方法

  Perl2EXE

  可以在大多數流行系統上編譯運作,但是我幾乎不用它,我認為它是“最低級”編譯。而且它也是最容易被反編譯的程式。是以我不推崇它,也不願意用它。不過适合很多初學者。

  它的原理很簡單,知識把原來的Perl代碼放入程式中和内置的解析其共同運作,而且速度不如PerlAPP。

  Perl2EXE

  同樣可以在

  http://ftp.tanshuai.net/pub

  和

  ftp://ftp.tanshuai.net/pub/

  下載下傳。

  标準方法:

  perl2exe

  Perl解析器選項值設定:

  perl2exe

  –perloption=““

  參數主要就是perl解析器的參數如:-w

  –X

  –e

  等等。

  共享dll庫:

  perl2exe

  –small

  如果你是多個程式編譯,那麼使用這個指令,比較“劃算“,你隻要把它們的共享dll庫,複制到共同的執行目錄下,即可。共享DLL庫:p2xdll.dll或者p2x560.dll。

  啟動圖形界面:

  perl2exe

  –gui

  和perlapp是同樣的作用。

  設定執行程式的圖示:

  perl2exe

  –icon=

  設定輸出檔案名:

  perl2exe

  -o=

  設定運作系統平台:

  perl2exe

  –platform=

  如:Sun作業系統

  perl2exe

  –platform=sun

  program.pl

  Linux作業系統

  perl2exe

  –platform=linux

  program.pl

  第三節

  PerlCC

  編譯方法

  PerlCC是Perl的最好最優秀最強的得編譯器,而且是免費的。但是它的調試與運作是比較方“煩”人的?L乇鹗竊谖⑷淼腤indows就更令人頭疼。

  PerlCC編譯器的原理是分析Perl原代碼,然後根據标準轉換方式,轉換成C語言,當然這裡的C全部采用Perl的頭檔案(Header),也就是全部采用Perl的函數,即使你隻有一行的

  “print

  “hello

  world”;”都需要無數行的定義後才會出現這樣的效果。但是令人驚奇的是perl編譯後的這個“hello

  world”比C/C++的編譯後的可執行檔案還要小。采用PerlCC轉換出來的C源代碼幾乎是不可讀(不可了解)的,幾乎比彙編語言還令人費解。是以這樣的程式即使被反編譯出來,它的源代碼也是會令人無法琢磨,但是這種程式根本幾乎無法反編譯,至少目前是,我相信隻要Windows未被反編譯那麼它編譯出來的Perl可執行程式也同樣無法反編譯。

  如果使用PerlCC是大家最關心的事情,在Unix-Style系統是,凡是安裝perl5.0以上版本的都可以使用PerlCC,編譯程式,但是必須有C編譯器。這個我就不必太多說了。因為這個方法不大适合初學者,一般中級程式員對Unix-Style系統應該是較為了解的。

  在Windows中,一定要安裝VC6.0(也可以是GCC,但是安裝複雜)否則仍然無法編譯,安裝VC6.0是簡單的事情,隻要找到微軟VC6的CD光牒,安裝。

  然後,下載下傳Perl源代碼(位址:http://ftp.tanshuai.net/pub/

  ),下來後解開壓縮(Windows可以用Winzip)。

  UNIX-Style

  指令行模式下:

  #cd

  #make

  #make

  test

  ~可選

  #make

  install

  ~完成安裝

  #export

  PATH=$PATH;/;

  ~設定變量

  Windows

  指令行(Command.com

  CMD.COM)模式下:

  C:/>cd

  C:

  nmake

  C:

  nmake

  test

  ~可選

  C:

  nmake

  install

  Windows

  95/98/Me

  在

  AutoExec.Bat檔案中設定路徑。

  Windows

  Nt/2000

  在“控制台”-〉“系統”-〉“進階”-〉“環境變量”中設定

  注意:千萬不要使用AtivePerl,而且最好在安裝标準編譯Perl後,删除AtivePerl,AtivePerl“不支援” PerlCC,雖然它也有帶perlcc

  但是至少我是永遠都無法編譯成功的,我也不知道為什麼,我也不想知道為什麼,因為很多程式是在Unix- Style

  上運作的,大多數都是标準Perl,是以建議大家為了相容所有作業系統,請盡量用标準Perl編寫和解析程式。

  好啦,一切安裝、設定就緒後,重新啟動計算機後。我們進入我們想要編譯的檔案目錄中,輸入“perlcc

  ”(注意:這裡的程式擴充名稱必須是.pl

  .bat

  .p

  .pm,.cgi也不行,你可以修改perlcc.bat檔案來支援其它擴充名)。

  輸入以上指令後,會出現一大堆你可能看不懂的指令(這些你并不需要關心)

  例如我要編譯一個内容為:

  print

  “ok”;

  的Perl程式,該檔案名:abc.pl。

  輸入:

  perlcc

  abc.pl

  PerlCC輸出内容:

  ------------------------------------------------------------------------------

  Compiling

  abc.pl:

  -------------------------------------------------------------------------------

  Making

  C(abc.pl.c)

  for

  abc.pl!

  C:/perl/5.6.0/bin/MSWin32-x86/perl.exe

  -IC:/perl/5.6.0/lib/MSWin32-x86

  -IC:/perl

  /5.6.0/lib

  -IC:/perl/site/5.6.0/lib/MSWin32-x86

  -IC:/perl/site/5.6.0/lib

  -I.

  -MB

  ::Stash

  -c

  abc.pl

  C:/perl/5.6.0/bin/MSWin32-x86/perl.exe

  -IC:/perl/5.6.0/lib/MSWin32-x86

  -IC:/perl

  /5.6.0/lib

  -IC:/perl/site/5.6.0/lib/MSWin32-x86

  -IC:/perl/site/5.6.0/lib

  -I.

  -MO

  =C,-l2000,-umain,-uattributes,-uDB,-uWin32

  abc.pl

  Starting

  compile

  Walking

 ?ree

  Prescan

  Saving

  methods

  Bootstrap

  attributes

  abc.pl

  Writing

  output

  Loaded

  B

  Loaded

  IO

  Loaded

  Fcntl

  abc.pl

  syntax

  OK

  Compiling

  C(abc)

  for

  abc.pl!

  C:/perl/5.6.0/bin/MSWin32-x86/perl.exe

  -IC:/perl/5.6.0/lib/MSWin32-x86

  -IC:/perl

  /5.6.0/lib

  -IC:/perl/site/5.6.0/lib/MSWin32-x86

  -IC:/perl/site/5.6.0/lib

  -I.

  E:/

  DOCUME~1/ADMINI~1/LOCALS~1/Temp/abc.pl.tst

  Couldn't

  open

  E:DOCUME~1ADMINI~1ocals~1temp/abc.pl.val

  cl

  -Od

  -MD

  -DNDEBUG

  -DWIN32

  -D_CONSOLE

  -DNO_STRICT

  -DPERL_MSVCRT_READFIX

  -Od

  -

  MD

  -DNDEBUG

  -Ic:/perl/5.6.0/lib/MSWin32-x86/CORE

  -o

  abc

  abc.pl.c

  /link

  -nologo

  -nodefaultlib

  -release

  -libpath:"c:/perl/5.6.0/lib/MSWin32-x86/CORE"

  -machine:

  x86

  -libpath:c:/perl/5.6.0/lib/MSWin32-x86/CORE

  c:/perl/5.6.0/lib/MSWin32-x86/CO

  RE/perl56.lib

  oldnames.lib

  kernel32.lib

  user32.lib

  gdi32.lib

  winspool.lib

  com

  dlg32.lib

  advapi32.lib

  shell32.lib

  ole32.lib

  oleaut32.lib

  netapi32.lib

  uuid.lib

  wsock32.lib

  mpr.lib

  winmm.lib

  version.lib

  odbc32.lib

  odbccp32.lib

  msvcrt.lib

  abc.pl.c

  然後再輸入:abc.exe,如果輸出結果與abc.pl一樣,那麼編譯就成功了。這個程式是使用Visual

  C++的CL.EXE

  C/C++編譯程式編譯的。在Unix-Style下是使用CC或者GCC編譯的。

  子產品編譯注意事項:

  目前PerlCC标準編譯方式可以支援大多數程式的子產品使用,但是我推薦盡量使用内部指令來完成相應任務,諸如IO::Socket子產品可以使用 socket

  内部函數。因為

  IO::Socket是無法在PerlCC下面編譯成功的,為什麼?

  大家知道Perl很多的子產品是本身Perl的語言和内部函數編寫的。但是有一部分包括IO::Socket

  DBD

  DBI等這些常用的子產品,由于Perl本身内置函數限制,采用了PerlXS接口通過C

  程式達到目的的。這些是通過第三方程式達到目的子產品是無法成功的編譯。是以我建議盡量使用非含有第三方程式的子產品程式設計。有人可能會說了,我使用了DBI

  DBD來操作資料庫,難道讓我放棄嗎?不,我覺得任何事情都是有它的解決方法,Perl也一樣。Perl

  Bytecode将會解決這一問題(詳情情看第4節)。

  程式設計方式注意事項:我為什麼要在開頭說OOP

  等相關技術以及在本文中提及了OOP的編寫?因為PerlCC編譯有一定的局限性,如果采用 OOP就可以避免這個局限性,而且會更好的發揮,衆所周知,OOP是程式設計發式的有一革命,你遲早都會涉及的,是以早一點總比晚一點好。我們經常編寫程式的時候用“require”指令來引用其它Perl程式檔案。然而這種方式不是PerlCC不支援,PerlCC當然支援,這個指令,但是問題在于它無法被編譯入PerlCC的主程式内,也就是說主程式被編譯了,然而外部引用的這個沒有被編譯,這樣會造成很多問題,首先是暴露了原始代碼,其次它人可以随意修改,肯能導緻很多量(比如密碼)被套出,也可以修改程式運作的模式。但是這也是有點,最後一節将會詳盡講述。

  第四節

  PerlCC之Bytecode

  編譯解析法

  Bytecode

  是

  PerlCC的另一編譯方法,必須在Perl5.6以後版本才有得支援。它的原理就好像Java一樣,它會把Perl檔案編譯成二進制令人費解的亂碼檔案,它是采用類似MD5這樣的反向加密編碼,幾乎不可能反編譯,和可執行程式一樣複雜,但是它不可以直接執行哦。想要執行它,必須用Perl解析器,就好像

  Java

  編譯後必須有Java解析器,否則就無法執行。我習慣成為編譯解析法,有的時候就說Just

  Like

  Java

  Progam!

  它的編譯方法也不難,但是竟然有很多人都不知道,我問過很多Perl前輩,他們也不大了解這一方法。而且很多我也從來見過誰寫過這樣的程式(難道我是國内第一個知道的嗎?:)

  使用方法:perlcc

  –b

  編譯後它會輸出一個檔案,你打開它看,定會吃驚。而且這種檔案最小是180KB,比perlcc

  C語言轉換編譯多了很多。

  它的好處在于,一處編譯到處使用。但是對于CGI就不大好處理。是以還是建議在各個平台進行編譯。

  例如我ByteCode編譯上節的abc.pl程式檔案:

  輸入:

  perlcc

  –b

  abc.pl

  Perlcc

  –B

  輸出

  ----------------------------------------------------------------------------

  Compiling

  abc.pl:

  ----------------------------------------------------------------------------

  Making

  Bytecode(abc.plc)

  for

  abc.pl!

  C:/perl/5.6.0/bin/MSWin32-x86/perl.exe

  -IC:/perl/5.6.0/lib/MSWin32-x86

  -IC:/perl

  /5.6.0/lib

  -IC:/perl/site/5.6.0/lib/MSWin32-x86

  -IC:/perl/site/5.6.0/lib

  -I.

  -MB

  ::Stash

  -c

  abc.pl

  C:/perl/5.6.0/bin/MSWin32-x86/perl.exe

  -IC:/perl/5.6.0/lib/MSWin32-x86

  -IC:/perl

  /5.6.0/lib

  -IC:/perl/site/5.6.0/lib/MSWin32-x86

  -IC:/perl/site/5.6.0/lib

  -I.

  -MO

  =Bytecode,-umain,-uattributes,-uDB,-uWin32

  abc.pl

  abc.pl

  syntax

  OK

  好了,然後perl

  abc.plc

  就可以執行了。

  執行注意事項:

  使用Bytecode

  編譯後的檔案,你一般需要更名回原來的檔案名,否則容易在運作程式後出現警告資訊“Attempt

  to

  free

  unreferenced

  scalar.”雖然它對程式沒有本質影響,但是不美觀嘛,另一種解決方法就是使用

  perl

  –X

  ,關閉所有警告消息,警告不等同與錯誤,是以一般情況下,某些警告是不必要的。

  同樣ByteCode

  編譯程式可以被引用(require)但是不能調用(use),可以作為對象程式設計的對象。這是一個很靈活的東西,如果你希望你的子產品被大家使用,但是不想讓大家知道其中的操作,那麼你就是用ByteCode,但是你的子產品将永遠不會被納入CPAN。這種方法就好像OCX控件。

  但是注意,但是使用某個子產品的時候,你必須保證使用該程式的機器上有這個子產品,最簡單的方法你可以把子產品一起複制使用,但是有些第三方程式子產品需要重新編譯,你如果不希望其它人操作子產品或者是看到引用的子產品,也可以使用 Bytecode。但是注意,一定要用require方法調用加密子產品啊。這個世界總是這樣,總會有些遺憾的,這樣的話就不能用一些子產品和OOP。

  不知道你了解Python這個語言否?它Perl很相像,比Perl還有簡單呢。但是我認為很多東西都是抄Perl的,包括它得二進制編譯方法,就和Perl

  Bytecode沒有任何差別。反正大家也都知道PHP也是抄了Perl不少東西。

  --------------------------------------------------------------------------------

  第五節

  OOP面向對象的程式之為編譯而設計

  面向對象的程式設計已經不是什麼新穎的話題和技術了。它在C++和Java中,尤為重要,哎,我覺得在寫大宗程式的時候會很有幫助,但是在小程式裡面反而麻煩,還不如普通的函數使用。OOP大多數基本的Perl教程都有說明,是以這裡也不多講“廢話”,主要講述OOP在編譯Perl程式中的應用以及Perl

  OOP編寫的技巧,是以值得一看。

  前面說過在PerlCC編譯可執行程式的時候,不要使用require函數,這是沒有錯的。但是有很多人寫require習慣了,而且不經常接觸OOP模式,是以不習慣。

  其實使用use比require

  好很多,還有很多人用require引入變量,這是大大錯誤,這是一種程式上編寫的失誤,是以建議以後大家不要用這種方式。編譯的時候也不要用這種放式?那麼用什麼方式?如果你是一個有經驗的Perl程式員,你應該知道。使用OPEN函數,傳送變量值。這是編譯Perl程式的關鍵,一些定量(不變的量),最好放在程式内部,變量以及客戶所需要設定的量使用我先前說的那種方式。具體實踐方法:

  Tanshuai

  OpenConf

  函數代碼:

  sub

  Open_Conf

  {

  open(FILE,

  "$_[0]");#打開~調用函數的檔案名

  my

  @Conf_Info

  =

  ;#賦予~檔案内容到@Conf_Info數組中

  close(FILE);#關閉~檔案

  my

  $Conf_Infos

  ;定義~局部變量

  foreach

  $Conf_Infos

  (@Conf_Info)

  {#循環

  ($name,

  $value)

  =

  split(/=/,

  $Conf_Infos);#區分~名稱和數值

  ($value,

  $dot)

  =

  split(/;/,

  $value);#區分~結束符

  $value=~s"'""gi;#删除~不必要的符号

  $CFG{$name}

  =

  $value;#複制~參數到散列變量

  }

  }

  配置檔案原形:

  Port='81';

  IP="127.0.0.1";

  Listen='5';

  調用方法:

  Open_Conf('../Conf/httpd.cfg');#../Conf/httpd.cfg為路徑和檔案名

  $port

  =

  $CFG{'Port'};#将檔案原型的Port量複制到$port上,當然你可以不必這樣做,可以直接引HASH

  $ip

  =

  $CFG{'IP'};#和上面的一樣

  這樣就解決了配置變量的問題,我想這個函數對某些人一定會有很重要的意義。

  在這裡OOP就是use

  方式的調用。

  現在我們要着重讨論OOP問題了,如果你不想把一大堆的程式代碼寫在一個檔案中,那麼使用OOP就最好了,原來是可以使用require,但這裡不可一。OOP在Perl的好處顯而易見,首先可以編譯,即使不編譯,它也同require有明顯差異。

  OOP是在程式需要時調入,不需要時自動消失(通常說破壞對象)。require則不然,一旦調入一直存在,除非你使用exit

  函數,是以在某些方面影響了程式的效率。

  例如我們要寫一個Shell程式,一共需要一下部分:輸入/輸出(I/O)、指令判斷(CMD)、System(系統操作)。

  我們平時也可以使用require,在編譯的時候就好了,同樣我們雖然可以按照子程式放在一個程式裡面,但是在這裡隻是例子,但是在大宗商業項目中,這樣做是顯然費時費力的,會增加維護成本,無法聯合開發等多種弊端。

  我們把他們分為4個檔案3個子產品一個主程式(編譯):IO.pm、CMD.pm、System.pm、Shell.pl。

  首先要構造對象:

  Tanshuai

  對象構造方法:

  package

  ;

  my

  %IN;#定義~包(對象)内部的散列

  sub

  new

  {#構造函數名

  my

  $class

  =

  shift;

  %IN=

  @_;#将調用對象的數值傳入散列IN中

  my

  $self={};

  bless

  $self,$class;

  return

  $self;

  }

  雖然上面的構造有些不好的地方,但是它是通用對象的構造方法,利于調試,如果你認為沒程式上的問題,就可以“封包”,适當修改變量傳引方式。

  這裡的所有對象隻有是一個單一函數,隻包括:構造對象和操作對象的兩個部分,這是一個簡單的對象引用,但是這種應用在實際的開發總是相當無畏的,在這裡是為了友善教大家,是以不要什麼程式都要對象。

  IO.pm:

  package

  IO;

  my

  %IN;

  sub

  new

  {

  my

  $class

  =

  shift;

  %IN

  =

  @_;

  my

  $self={};

  bless

  $self,$class;

  return

  $self;

 ?

  sub

  do

  {#操作對象函數

  my

  $self=shift;

  defined

  ($_

  =

  );#啟動Shell得取輸入資訊

  chomp;#去掉無用的字元

  s/^/s+//;#過濾危險字元

  my

  $cmd

  =

  $_;#複制量

  return

  $cmd;#傳回量

  }

  1;

  CMD.pm:

  package

  CMD;

  my

  %IN;

  sub

  new

  {

  my

  $class

  =

  shift;

  %IN

  =

  @_;

  my

  $self={};

  bless

  $self,$class;

  return

  $self;

  }

  sub

  do

  {#操作對象函數

  my

  $self=shift;

  my

  $cmd

  =

  @_

  ;#傳入調用程式的指令

  while

  (){#執行循環,直到退出

  if

  ($cmd

  eq

  'ver')

  {

  print

  "Tanshuai

  Command

  Shell

  v.1.0.0.001225b/n";

  print

  "(C)Copyright

  Tanshuai.Com

  1997-2001/n";

  print

  'EMAIL:[email protected]';

  print

  "/n";

  &do;

  }

  elsif

  ($cmd

  eq

  ""){

  &do;

  exit;

  }

  elsif

  ($cmd

  eq

  'exit'){

  print

  "Exit

  System";

  exit;

  }

  elsif

  ($cmd

  eq

  ‘dir'){

  use

  System;#使用包System

  my

  $sys

  =

  System

  ::new

  ;#建立基于System包的對象$sys

  $sys->do($cmd)

  ;#操作對象sys傳送指令

  &do;

  }

  else

  {

  print

  "

  Command

  Not

  Found

  ";

  &do;

  }

  }

  }

  }

  1;

  System.pm:

  Package

  System;

  my

  %IN;

  sub

  new

  {

  my

  $class

  =

  shift;

  %IN

  =

  @_;

  my

  $self={};

  bless

  $self,$class;

  return

  $self;

  }

  sub

  do

  {#操作對象函數

  my

  $self=shift;

  my

  $cmd

  =

  @_

  ;

  system($cmd)

  ;#使用System函數作業系統,啟動dir指令

  1;

  以上各個子產品(對象)已經建立完畢,我們現在隻需要設計一個簡單的操作對象程式。這個時候你發現搞對象原始是如此簡單:)

  Shell.pl

  主程式:

  use

  IO;#調用~子產品(對象)

  IO.pm

  use

  CMD;#調用~子產品(對象)

  CMD.pm

  my

  $IO

  =

  IO::new;#建立對象~$IO

  my

  $CMD

  =

  CMD::new;#建立對象~$CMD

  my

  $GetInput

  =

  $IO->do;#從對象IO得到輸入資訊;

  $CMD->do("$GetInput");#将得到的輸入資訊發送給對象$CMD,進行分析操作。

  exit

  ;

  這樣就完成了,你可能問為什麼沒有使用對象System

  ?那是因為在對象CMD中繼承對象System,是以我們不需要在程式中使用System,要不然就累了。

  當你看到shell.pl程式時候,你有何感想?是不是覺得搞對象簡單了很多呢?給我的想法就是,以後程式員會越來越多,因為對象程式設計太簡單了,而我們呢?哎,我們就去做對象。以後程式設計和做對象的人可能要區分開來了。

  現在編譯shell.pl後,把這些對象删除,看看能否使用?當然能,假如你使用require就出現無法執行的緻命錯誤。

  哎呀,好累了。我就要吐血了

  #[email protected],還沒有吃晚飯呢。明日繼續吧。

  這裡告訴大家編譯Perl在較大或者較複雜的程式項目中,使用對象,會有很好的作用。你可能會問,用對象編譯出來的程式如此之大,是否會影響效率?肯定會,但是它并非明顯,就好像一個小小的15KB的程式,在運作的時候可能占用超過100MB的記憶體。由于它會整個被記憶體啟動,但是并不會有較大幅度的效率下降。如果還想使用類似require的方法,就要看最後一章了。

  第六節

  HTML模闆程式設計方式——真正的WEB程式

  什麼是真正的程式(Program)?我們平時使用ASP、PHP這些都不屬于程式,它們隻是一種頁(Page),動态頁面(Dynamic

  Page),但是我們一般稱作頁面程式設計(Web

  Programming),但這種說法不确切(并非不正确)。程式就是程式,并非所有的語言都叫做程式或程式設計語言。很多權威的書籍、文章和網站(例如:Yahoo!)都沒有将ASP、PHP當作程式(程式設計語言)來解釋。ASP是一種語言媒體,PHP在 Yahoo的定義頁隻是類似于SSI。他們說要做的東西頂多就是一個“背景(伺服器端)的HTML(或者說是Script)”,可以想象,頁(Page)和程式(Program)的差異,至少可以說頁是由程式來解析輸出結果的。那麼也就是說,頁想要做的事情比程式要局限得多。PHP不是一種程式,如果用 ASP或PHP做一個Http伺服器,你會有什麼感覺?你見過嗎?你見過ASP、PHP做的非Web“程式”嗎?我想你沒有見過。你相信用ASP、PHP 編制出類似于Windows的圖形(GUI)界面程式嗎?那是一種什麼感覺呢?是以,做程式和頁面是兩種不同的概念,在國内不知道是翻譯的時候錯誤,還是大家都是這樣了解的。

  如果你要寫一個Web頁,做一些小動作,用ASP、PHP、ePerl等未嘗不可。但是它不是來給你做大宗Web項目或者軟體而設計的。至少我是這樣認為。而且我覺得Perl目前在程式中直接使用HTML是一種不好的習慣或者行為。它将增加維護成本,降低工作效率等諸多不便因素。其實我覺得外制式的模闆方式的HTML套入法是适合時代潮流以及未來軟體更新擴充的。至少可以讓客戶在不觸及程式核心的前提下,随意修改界面,可以得到個性化、特性化的設定——未來趨勢。而且我們可以降低很大維護的成本,同時某些不變的(諸如:版權、聲明、标示)内容仍然可以使用内置式或者在套入模闆的過程中進行相應修改等。如果你真的不喜歡他人修改模闆,那麼你可以使用加密方式,對模闆檔案進行加密,可以達到程式操作目的,和降低維護成本,而禁止他人修改的目的(推薦使用:Crypt::RC4)。

  本章将會着重講述在Perl程式中(不但隻是為了編譯Perl)使用套入法,套入模闆HTML,并且進行靈活的HTML操作。

  以下是标準的内置式和外制式的HTML操作:

  内置式HTML程式:

  #!perl

  $Var="HELLO

  WORLD";

  print

  $Var

  HTML

  exit;

  外置式HTML程式:

  #!perl

  $Var="HELLO

  WORLD";

  open

  (HTML,"../HelloWorld.html");#打開HelloWorld.html檔案

  @HTML=;

  close

  (HTML);

  print

  Content-type

  :text/html

  ;

  foreach

  (@HTML)

  {#循環

  $_

  =~

  s//*Var/$Var/g;#替換Hellworld.html

  檔案中*Var的内容為變量$Var的内容

  print

  "$_";#輸出

  }

  exit;

  外置式HTML檔案

  HellWorld.html:

  *Var

  上面的例子都是現實操作中廣泛(流行)用法,大家可能感覺到外置式有些複雜,其實不然,你隻要把它做成一個函數或者對象就相當容易了。

  關鍵問題在于,變量的替換,若使用上面的方法,有些不妥,因為默寫模闆頁面不一定是适合的那些變量,如果你把所有的變量都放在foreach裡面,那麼勢必對于程式運作資源造成極大浪費,而且得?懷ナВ跋煨省U庋龀梢桓龊蛘叨韻螅曰嵊脅煌ㄓ玫奈侍狻?

  是以建立一個靈活的分析方法,對于模闆HTML處理提供良好的快捷的運作模式。

  這個時候我們就要利用Perl強大的文法分析,來做一個自己的HTML語言分析語句了。這個語句看似簡單缺令人頭疼。

  我們現在以“*”符号作為模闆中的變量(類似于Perl

  中的$),這樣有助于辨析。那麼我想要把所有以“*”開頭的變量,自動變換成程式内的對應變量,例如:要把*abc成為内部的$abc。一般情況我們需要逐個設定,這樣大大浪費了時間,我們現在需要做一個通用的方法,無論什麼的量都自動轉換。這個文法很簡單:

  $_

  =~

  //*(/w+)/;

  看似簡單的一局話,卻有很大的作用,這句就是把以*開頭的字元的名找出來,但是有趣的是,你不需要進行太複雜的,隻要遇到空格或者其它非标準字元,就會自動排除。

  現在我們要把找到的字元名(即HTML的自定義變量)發給一個臨時變量中(該步驟可以不做):$tmp

  =

  $1

  ;

  現在要做的就是把這個*abc換成量$abc的值:

  $_

  =~

  s//*$tmp/$Html{"$tmp"}/g

  這裡的$Html是散列變量(HASH),為了友善和容易了解,我在這裡采用HASH,這樣對應的$Html{‘abc’}就被提出來,換掉*abc了。

  下面就是我做的模闆套用函數與例子。

  打開檔案的函數RTF:

  #!perl

  sub

  RTF{

  open(READTXTFILE,"$_[0]");

  @readtxtfile=;

  close(READTXTFILE);

  return

  @readtxtfile;

  }

  分析模闆的函數PHF:

  #!perl

  sub

  PHF

  {

  my

  $file

  =

  "$_[0]";

  @HtmlFileMessages=&RTF("$file");#Open

  File;

  foreach

  (@HtmlFileMessages)

  {

  $_

  =~

  //*(/w+)/;

  #替換網頁的變量,批量處理,尋找“*

  --------------------------------------------------------------------------------

  第七節

  聯合編譯以及執行個體

  本章至關重要,你已經知道Perl的兩種最好的編譯方法。但是他們都有利弊,隻要稍動腦筋,就可以實作“強強聯合”,這樣可以盡量避免那些缺憾。

  聯合編譯的道理很簡單,但操作起來也不那樣一帆風順,其中有很多地方值得注意。聯合編譯主要有一個主程式和多個子程式(FILE)組成。它們之間是使用require函數連接配接。主程式隻做連接配接等分析工作,子程式做細節工作,包括對象操作,子產品引用。我們采用PerlCC

  翻譯C的方式來編譯主程式成為一個可以執行的檔案,在把子程式用Bytecode方式編譯,這樣即可免去無法使用部分子產品的問題,也可以直接使用Perl程式,隻要在主程式的前面定義一下子產品引用路徑,方法:

  use

  lib

  ‘’;

  這樣就可以了,把那些需要調入的子產品,放在制定路徑中就好了。而且在CGI或者Socket的網絡程式設計和頁面程式設計中,使用該模是有助于提高效率,降低資源占用率。如果使用整體編譯方法,那麼每次啟動必然會耗費相當大的記憶體,同樣這個程式要重複關閉啟動,做Fast

  CGI也是相當不友善的,這也是 Fast

  CGI在Perl中的最好的方法。根據不同的請求套入不同的子程式。

  首先我們使用

  cgi-lib.pl得去POST和GET資料(這個時候有些人會問,為什麼不使用cgi.pm,我不是不想用它,而是cgi.pm在perlcc的任何編譯模式都會有問題)

  然後根據不同的請求,我在這裡設定為action。

  例如:

  require

  “cgi-lib”;

  if

  ($in{‘action’}

  eq

  “”)

  {

  require

  “display.pl”;

  &display;

  exit;#可選

  }elsif

  ($in{‘action’

  }eq

  “love”)

  {

  require

  “love.pl”;

  &love;

  exit;#可選

  }

  這樣是很好的。我們使用perlcc

  标準編譯方法編譯它,然後用-b模式編譯display.pl和love.pl。然後把它們的名字改回.pl。

  注意在使用perlcc編譯程式的時候,編譯出來的程式必須帶有應用程式擴充檔案,如dll和so。因為你的程式還需它們支援,這個檔案在 Perl的解析軟體目錄下,例如perl5.6就是perl56.dll,必須把它拷貝到執行檔案目錄地下。在Linux下是.so。你最好在一個沒有 Perl

  平台解析器的環境下進行測試,把那些需要使用的包也包括在裡面。即使是VC等軟體編譯出來的程式,都需要在純環境下測試,這是必要的。這樣就可以測試出程式的一些不必要的問題。

  另外perlcc

  的任何模式對文法都是很挑剔的,是以你最好使用比較正規的編寫方法,而且單個perl程式如果程式量太大,必須截取到另一個檔案中,否則編譯後容易出現記憶體溢出現象。

  大家要知道如果你的子程式使用了ByteCode編譯,但是他人仍然可以把你的子程式改成源代碼形式,這樣就好像我說的會被套出很多量。最好的的方法,是采用ByteCode

  編譯的程式寫入一個Auth認證函數。當然最保險的方法是使用檔案内容驗證,但是效率影響,我認為不大必要。

  主程式:

  #

  !perl

  require

  “cgi-lib”;

  if

  ($in{‘action’}

  eq

  “”)

  {

  auth

  (“display.pl”);

  &display;

  exit;#可選

  }elsif

  ($in{‘action’

  }eq

  “love”)

  {

  auth

  (“love.pl”);

  &love;

  exit;#可選

  }

  sub

  auth

  {

  require

  "$_[0]

  "

  ;

  $auth

  =

  &check

  ;

  if

  ($auth

  ne

  "checkabcdefg

  "){

  exit

  ;

  }

  }

  Display.pl

  #

  !perl

  sub

  check

  {

  $check=

  "checkabcdefg

  "

  ;

  return

  $check

  ;

  }

  sub

  display

  {

  print

  "content-type

  :text/html

  /n/n"

  ;

  print

  "hello

  baby

  "

  ;

  }

  上面是一種簡單的,不過也會造成一些問題,是以下面是一個麻煩(并非複雜)方法,但是很安全。

  檢查編譯程式是否真實:

  #

  !perl

  open

  (FILE,"./print.pl");

  @FILE=;

  close

  (FILE);

  foreach

  (@FILE)

  {

  if

  ($_

  =~/程式編譯後的部分代碼/){

  }else

  {exit

  ;}

  }

  首先把程式進行bytecode編譯,然後截取部分獨特的其它程式沒有的代碼,放入其中,來檢查引入程式是否正确合法。

  你可以把bytecode的程式改名成.dll等,這樣其它人就不知道是怎麼回事啦。

  結束語

  Perl是一個強大的而且是最早的解析性程式語言,它的編譯程式是B子產品,大家可以詳細常見,它有多種編譯方式,都是采用反向編譯(BackEnd)不同于反編譯。是以經本上是不可能被反編譯。我認為本文對所有的Perl程式員都有很大的幫助。

  Perl還有很多其它方式的編譯、加密方法,但是我覺得本文介紹的幾種方式都是最好的(相容性和運作效率),有一些人,把寫的程式進行部分字元亂碼或者是取消縮近的書寫格式(把所有程式寫在一行上),我認為這些方法是“愚蠢的”,是以建議大家不要花那麼多時間去研究這些“無謂”的東西。

  部分字元編碼例子——原本:

  #

  !perl

  sub

  Hello

  {

  $hello=abc

  ;

  print

  $hello

  ;

  }

  &hello

  ;

  部分字元編碼例子——編碼後

  #

  !perl

  sub

  adfjierei123489dkajd_dfefnkdj

  {

  $iernvmdnvcjnaldffgh=abc;

  print

  $iernvmdnvcjnaldffgh;

  }

  &adfjierei123489dkajd_dfefnkdj;

  我希望通過本文促使Perl在國内的商業發展,也同樣加快了Perl技術在國内的發展速度。但是我仍然希望大家可以寫更多的公開源代碼的程式出來,這樣可以讓初學者有較快的提高速度。

  如果你有任何問題和想法都可以通過電子郵件([email protected],

  [email protected],

  [email protected])或者ICQ:25856530

  OICQ:66552聯絡我,其它資料可以到我的網站查詢http: //www.tanshuai.net

  http://www2.tanshuai.net  

本文來自:Linux教程 -- http://doc.linuxpk.com/3089.html

如有不明白之處,歡迎參加社群讨論