27 Eylül 2012 Perşembe

Fuzuli ile İki String Arasındaki Levenshtein Uzaklığını Hesaplama

Geçtiğimiz aylarda yayınlanan Fuzuli Programlama Dili ve Yorumlayıcı'nın (Interpreter) ilk sürümünden itibaren gerek bu blog içerisinde, gerekse stdioe.blogspot.com İngilizce blog içerisinde Fuzuli ile ilgili tanıtıcı ve öğretici yazılar yazmaktayız. Bu yazıda da oldukça yararlı olan ve bir çoğumuzun bilip kullandığı levenshtein fonksiyonunu, Fuzuli içerisinde kullanıp iki string ifadenin arasındaki uzaklığı hesaplayacağız.

Fuzuli kodunda anlamadığınız yerleri http://fuzuliproject.org/docs/ adresinden Fuzuli Documentation başlığı altında araştırıp, http://fuzuliproject.org/index.php?node=tryonline adresindeki online interpreter üzerinde online olarak çalıştırıp çıktısını görebilirsiniz.


(require "nfl/io.nfl")
(require "nfl/string.nfl")
 
(print "Please enter a word for calculating distance: ")
(let word (readline))
 
(let Array (list "windows" "ubuntu" "android"))
 
(foreach i in Array
  (let distance (levenshtein word i))
  (println distance " for " i)
)

Yukarıdaki kodlar, Fuzuli ile yazılmıştır. Fuzuli kodları ile yazılan sayfalar, .fzl dosya formatında kaydedilir. Biz de yukarıdaki dosyamızı levenshtein.fzl adıyla kaydedelim. Şu an Fuzuli 'nin Linux ve Windows sürümleri mevcuttur. Ancak Windows sürümü limitlidir ve her paketi içermez. Levenshtein fonksiyonu ve konsolda kullanıcıdan girdi bekleyen readline, sırasıyla string ve io paketlerinde olduklarından, bizim örneğimizin çalışması için, bu fonksiyonları içeren bir Fuzuli versiyonu yeterli olacaktır. Windows limitli sürümü ise bu paketleri içerir.

Windows limitli sürümünü indirmek için : http://code.google.com/p/fuzuli/downloads/detail?name=fuzuli-0.1.10-Windows.zip&can=2&q=

Konsolda

fuzuli levenshtein.fzl

yazıp enter tuşuna bastığınızda





Yukarıdaki gibi ekran çıktılarını alacaksınız. İlk ekran çıktısında kullanıcı girdisi "fuzuli" olmuştur ve  levenshtein fonksiyonu windows, ubuntu ve android kelimeleriyle aradaki uzaklığı hesaplayıp ekrana sırasıyla 6, 5, 5 yazdırmıştır. Ancak ikinci ekran çıktısında kullanıcı girdisinin "android" olduğu görülmektedir. Dolayısıyla levenshtein fonksiyonu, son satırda "0" bulmuştur, zira android kelimesi ile android kelimesi arasındaki fark, sıfır (0) olacaktır.

Kod sentaksı ile ilgili sorularınızın cevaplarını http://fuzuliproject.org sitesinde bulabilir, Fuzuli Kılavuzunu ise android cihazınıza Google Market üzerinden indirebilirsiniz.

Bol fuzuli günler dilerim.

3 Temmuz 2012 Salı

Çoklu Dynamips Servisi için Dynagen Örnek Çalışması


http://stdioe-tr.blogspot.com/2012/07/coklu-cisco-router-simulasyonu-icin.html bağlantısında Çoklu Cisco Router Similasyonu için bir Dynagen & Dynamips örnek çalışmasını anlatmıştım. Bu yazımda ise, birden fazla dynamips servisini birden kullanan bir dynagen uygulaması anlatacağım. Ayrıca dynagen performans optimizasyonu hakkında bir detaydan bahsedeceğim


Bu örnekte 3 adet dynamips servisimiz olacak. Her dynamips servisi ise 3 adet sanal yönlendirici barındıracak ve 9 sanal yönlendirici de birbirine bağlı olacaklar. İlk dynamips servisi R1, R2 ve R3 yönlendiricilerini, ikinci dynamips servisi R4, R5 ve R6 yönlendiricilerini ve üçüncü dynamips servisimiz ise R7, R8 ve R9 yönlendiricilerini içerecekler. Bu 9 yönlendirici konfigüresyon dosyasında 3 erli guruplar halinde ayrı gibi görünselerde, mantıksal olarak her biri bir diğerine bağlı olacaklar.


Topolojimiz ve bağlantılar;


1-) dynamips servislerinin farklı port numaraları ile başlatılması,

ismail@ismail-ThinkPad-T410:~$ dynamips -H 7200 &
ismail@ismail-ThinkPad-T410:~$ dynamips -H 7301 &
ismail@ismail-ThinkPad-T410:~$ dynamips -H 7402 &

2-) dynamips konfigürasyon dosyasının topolojiye göre oluşturulması,

###############################1-Dynamips-1#############################
[localhost:7200]
  udp=10000
  workingdir = /tmp/workingdy1

[[3725]]
  image = /tmp/c3725-adventerprisek9-mz.124-15.T13.bin
  ram = 128
  #idlepc =  ?? # We will talk about this, later.
  ghostios = true
  sparsemem = true
  idlemax = 100 
  disk0=128

 [[Router R1]]
  model = 3725
  console = 2001
  autostart = false
  S0/0 = R2 S0/0

 [[Router R2]]
  model = 3725
  console = 2002
  autostart = false
  S0/0 = R1 S0/0
  S0/1 = R3 S0/0

 [[Router R3]]
  model = 3725
  console = 2003
  autostart = false
  WIC0/0 = WIC-2T
  S0/0 = R2 S0/1 
  S0/1 = R7 S0/1

###############################1-Dynamips-1#############################

###############################2-Dynamips-2#############################
[localhost:7201]
  udp=11000
  workingdir = /tmp/workingdy2

[[3725]]
  image = /tmp/c3725-adventerprisek9-mz.124-15.T13.bin
  ram = 128
  #idlepc =  ?? # We will talk about this, later.
  ghostios = true
  sparsemem = true
  idlemax = 100 
  disk0=128

 [[Router R4]]
  model = 3725
  console = 2004
  autostart = false
  S0/0 = R5 S0/0
  S0/1 = R8 S0/1

 [[Router R5]]
  model = 3725
  console = 2005
  autostart = false
  S0/0 = R4 S0/0
  S0/1 = R6 S0/0

 [[Router R6]]
  model = 3725
  console = 2006
  autostart = false
  S0/0 = R5 0/1

###############################2-Dynamips-2#############################

###############################3-Dynamips-3#############################
[localhost:7202]
  udp=12000
  workingdir = /tmp/workingdy3

[[3725]]
  image = /tmp/c3725-adventerprisek9-mz.124-15.T13.bin
  ram = 128
  #idlepc =  ?? # We will talk about this, later.
  ghostios = true
  sparsemem = true
  idlemax = 100 
  disk0=128

 [[Router R7]]
  model = 3725
  console = 2007
  autostart = false
  S0/0 = R9 S0/0
  S0/1 = R3 S0/1

 [[Router R8]]
  model = 3725
  console = 2008
  autostart = false
  WIC0/0 = WIC-2T
  S0/0 = R9 S0/1
  S0/1 = R4 S0/1

 [[Router R9]]
  model = 3725
  console = 2009
  autostart = false
  S0/0 = R7 0/0
  S0/1 = R8 0/0

###############################3-Dynamips-3#############################

Yukarıdaki konfigürasyon metnini sample2.net ismi ile /tmp dizini altına kayıt ettim. Yine bu örnekte de working dizinlerine ihtiyacım olacak, oluşturuyorum:
ismail@ismail-ThinkPad-T410:~$ mkdir /tmp/workingdy1
ismail@ismail-ThinkPad-T410:~$ mkdir /tmp/workingdy2
ismail@ismail-ThinkPad-T410:~$ mkdir /tmp/workingdy3

3-) Working dizinleri hazır. Şimdi dynagen servisi başlatılmaya hazır. Sorun çözme hakkında bir şeyler göstermek için bir hata yapıyorum,

ismail@ismail-ThinkPad-T410:~$ dynagen /tmp/sample2.net 
Reading configuration file...

Shutdown in progress...
Shutdown completed.
Shutdown in progress...
Shutdown completed.
Shutdown in progress...
Shutdown completed.
*** Warning:  Connecting R6 S0/0 to R5 0/1 resulted in:
 malformed destination interface: R5 0/1
*** Warning:  Connecting R9 S0/0 to R7 0/0 resulted in:
 malformed destination interface: R7 0/0
*** Warning:  Connecting R9 S0/1 to R8 0/0 resulted in:
 malformed destination interface: R8 0/0

*** Error:  errors during loading of the topology file, please correct them
Shutdown in progress...
Error: could not communicate with dynamips server localhost
It may have crashed. Check the dynamips server output.
Exiting...
Press ENTER to exit
[3]+  Segmentation fault      (core dumped) dynamips -H 7202
ismail@ismail-ThinkPad-T410:~$ 

Normalde bir hattın her iki ucu için de bağlantı tanımlayabilirsiniz. Ancak görüldüğü gibi dynagen servisi bu çift tanımlamayı kabul etmiyor. R5 yönlendiricisinde, " S0/1 = R6 S0/0" bağlantısını kaldırıyorum. Aynı şekilde R7 yönlendiricisinden, "  S0/0 = R9 S0/0" bağlantısını ve R8 yönlendiricisinden, " S0/0 = R9 S0/1" bağlantısını kaldırıyorum. Bu düzenlemeden sonra sample2.net dosyası aşağıdaki gibi son halini alıyor;






###############################1-Dynamips-1#############################
[localhost:7200]
  udp=10000
  workingdir = /tmp/workingdy1

[[3725]]
  image = /tmp/c3725-adventerprisek9-mz.124-15.T13.bin
  ram = 128
  #idlepc =  ?? # We will talk about this, later.
  ghostios = true
  sparsemem = true
  idlemax = 100
  disk0=128

 [[Router R1]]
  model = 3725
  console = 2001
  autostart = false
  S0/0 = R2 S0/0

 [[Router R2]]
  model = 3725
  console = 2002
  autostart = false
  #S0/0 = R1 S0/0
  S0/1 = R3 S0/0

 [[Router R3]]
  model = 3725
  console = 2003
  autostart = false
  #S0/0 = R2 S0/1
  S0/1 = R7 S0/1

###############################1-Dynamips-1#############################

###############################2-Dynamips-2#############################
[localhost:7201]
  udp=11000
  workingdir = /tmp/workingdy2

[[3725]]
  image = /tmp/c3725-adventerprisek9-mz.124-15.T13.bin
  ram = 128
  #idlepc =  ?? # We will talk about this, later.
  ghostios = true
  sparsemem = true
  idlemax = 100
  disk0=128

 [[Router R4]]
  model = 3725
  console = 2004
  autostart = false
  S0/0 = R5 S0/0
  S0/1 = R8 S0/1

 [[Router R5]]
  model = 3725
  console = 2005
  autostart = false
  #S0/0 = R4 S0/0
  S0/1 = R6 S0/0

 [[Router R6]]
  model = 3725
  console = 2006
  autostart = false
#  S0/0 = R5 0/1

###############################2-Dynamips-2#############################

###############################3-Dynamips-3#############################
[localhost:7202]
  udp=12000
  workingdir = /tmp/workingdy3

[[3725]]
  image = /tmp/c3725-adventerprisek9-mz.124-15.T13.bin
  ram = 128
  #idlepc =  ?? # We will talk about this, later.
  ghostios = true
  sparsemem = true
  idlemax = 100
  disk0=128

 [[Router R7]]
  model = 3725
  console = 2007
  autostart = false
  S0/0 = R9 S0/0
  #S0/1 = R3 S0/1

 [[Router R8]]
  model = 3725
  console = 2008
  autostart = false
  S0/0 = R9 S0/1
  #S0/1 = R4 S0/1

 [[Router R9]]
  model = 3725
  console = 2009
  autostart = false
#  S0/0 = R7 0/0
#  S0/1 = R8 0/0

###############################3-Dynamips-3#############################


dynamips servislerini 7200, 7201 ve 7202 portları üzerinden zaten çalıştırmışdık. Ancak dynagen servisimiz başarısı olduğu için, bazı dynamips servislerinin de çökmüş olma olasılığı sözkonusu. Bu sebeple öncelikle dynamips servislerinin tamamının çalışmaya devam ettiğinden emin olmalıyız.



ismail@ismail-ThinkPad-T410:~$ ps -ef | grep dynamips
ismail    3811  3756  1 10:15 pts/0    00:00:14 dynamips -H 7200
ismail    3829  3756  1 10:16 pts/0    00:00:14 dynamips -H 7201
ismail    4017  3756  0 10:27 pts/0    00:00:00 grep --color=auto dynamips


Aldığımız cevaba göre, bir dynamips servisi çökmüş ve diğer ikisi çalışmaya devam ediyor. Ben tüm dynamips servislerini öldürüp, hepsini baştan çalıştırmayı tercih ediyorum. Bunun için 3811 ve 3829 PID noları ile tek tek öldürmek de mümkün (kill -9 3811 gibi..) ancak pkill ile tümünü birden öldürmek daha pratik geliyor,



ismail@ismail-ThinkPad-T410:~$ pkill dynamips
[1]-  Terminated              dynamips -H 7200
[2]+  Terminated              dynamips -H 7201
ismail@ismail-ThinkPad-T410:~$ 


ve şimdi çalışan dynamips servisi kalmadı,
onları tekrar baştan başlatabilirim ve dynagen topolojisini yükleyebilirim;



ismail@ismail-ThinkPad-T410:~$ dynamips -H 7201 &
ismail@ismail-ThinkPad-T410:~$ dynamips -H 7202 &
ismail@ismail-ThinkPad-T410:~$ dynamips -H 7203 &
ismail@ismail-ThinkPad-T410:~$ dynagen /tmp/sample2.net 
Reading configuration file...
...
...
...
Dynagen management console for Dynamips and Pemuwrapper 0.11.0
Copyright (c) 2005-2007 Greg Anuzelli, contributions Pavel Skovajsa

=> 


Nihayetinde dynagen topologiyi yükledi. Yukarıda dynagen konsoluna düştüğümüzü görüyorsunuz. Burada "start R1" gibi yönlendirici isimlerine start komutları göndererek onları tek tek başlatabiliriz. Ya da "start /all" ile hepsini birden başlatmak da mümkün.

Bilgisayarımızda 9 adet sanal yönlendirici çalışıyor.. Sanırım şimdi performans için biraz optimizasyon yapmak gerekebilir. Bunun için "idlepc" parametresinin değerini tespit edip dynagen konfigürasyon dosyasında yerine yazmamız gerekiyor. idlepc değeri her yönlendirici için farklı değerler alabilir ve onu öğrenmek için ilgili yönlendiriciyi başlatıp, "idlepc get Rx" komutu ile ilgili yönlendirici için idlepc değerlerini listeyebiliriz.


=> start R1
=> idlepc get R1
Please wait while gathering statistics...

Please wait while gathering statistics...
Done. Suggested idling PC:
   0x60c08128 (count=22)
   0x60c08164 (count=33)
   0x60c08180 (count=35)
   0x60c081c0 (count=66)
   0x62b2823c (count=45)
   0x60c08bf8 (count=23)
   0x60c08c20 (count=20)
   0x614b0e34 (count=38)
   0x62b2b134 (count=20)
   0x6026bca4 (count=30)
Restart the emulator with "--idle-pc=0x60c08128" (for example)
   1: 0x60c08128 [22]
   2: 0x60c08164 [33]
   3: 0x60c08180 [35]
   4: 0x60c081c0 [66]
   5: 0x62b2823c [45]
   6: 0x60c08bf8 [23]
   7: 0x60c08c20 [20]
   8: 0x614b0e34 [38]
   9: 0x62b2b134 [20]
  10: 0x6026bca4 [30]
Potentially better idlepc values marked with "*"
Enter the number of the idlepc value to apply [1-10] or ENTER for no change: 
No changes made
=> 


Eğer listelenen idlepc değerlerinden herhangi birinin önünde "*" karakteri var ise, bu önerilen değerdir, kullanabiliriz. Ağer henüz bir değer önerilmemiş ise, "idlepc get Rx" komutu ile tekrar değerler üretilmesini isteyebiliriz. "*" 'li satır tespit ettiğimizde hedefimize ulaşmışız demektir.

Çoklu Cisco Router Simulasyonu için Dynagen & Dynamips Örnek Çalışması


     Eğer tek bir cisco router simule etmek istiyorsanız sadece dynamips kullanmanız yeterlidir. Ancak birden fazla Cisco yönlendiriciyi birbirine bağlayıp bir topolojiyi ayağa kaldırmak istiyorsanız (sanal / simulasyon ortamında) bu durumda dynagen'i de işe katmanız gerekir.


     Ben bu örnekte Ubuntu 12.04 kullandım. Tariflerim bu işletim sistemi için olsada dynagen çalıştırabileceğiniz tüm işletim sistemleri için rehberlik edebilir. Öncelikle dynagen (ve bağımlılık kontrolü sayesinde dynamips de) uygulamasını yüklüyorum.

ismail@ismail-ThinkPad-T410:~$ sudo apt-get install dynagen 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  dynamips python-configobj
The following NEW packages will be installed:
  dynagen dynamips python-configobj
0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,070 kB/1,418 kB of archives.
After this operation, 4,263 kB of additional disk space will be used.
Do you want to continue [Y/n]? 
Get:1 http://tr.archive.ubuntu.com/ubuntu/ precise/main python-configobj all 4.7.2+ds-3build1 [233 kB]
Get:2 http://tr.archive.ubuntu.com/ubuntu/ precise/multiverse dynagen all 0.11.0-6 [836 kB]
Fetched 1,070 kB in 0s (1,495 kB/s)
Selecting previously unselected package dynamips.
(Reading database ... 206573 files and directories currently installed.)
Unpacking dynamips (from .../dynamips_0.2.7-0.2.8RC2-5ubuntu1_amd64.deb) ...
Selecting previously unselected package python-configobj.
Unpacking python-configobj (from .../python-configobj_4.7.2+ds-3build1_all.deb) ...
Selecting previously unselected package dynagen.
Unpacking dynagen (from .../dynagen_0.11.0-6_all.deb) ...
Processing triggers for man-db ...
Processing triggers for doc-base ...
Processing 1 added doc-base file...
Registering documents with scrollkeeper...
Setting up dynamips (0.2.7-0.2.8RC2-5ubuntu1) ...
Setting up python-configobj (4.7.2+ds-3build1) ...
Setting up dynagen (0.11.0-6) ...
Processing triggers for python-support ...
ismail@ismail-ThinkPad-T410:~$ 


     İhtiyacımız olan uygulamalar artık işletim sistemimizde mevcut. Şimdi de örnek network topolojimize geçelim,
     Bu örneğe göre 3 adet Cisco Router simule edeceğiz. Bunun için tek bir dynamips servisinin yeterli olacağını düşünüyorum.

1-) dynamips servisinin başlatılması;

ismail@ismail-ThinkPad-T410:~$ dynamips -H 7100 &
[1] 16919
Cisco Router Simulation Platform (version 0.2.8-RC2-amd64)
Copyright (c) 2005-2007 Christophe Fillot.
Build date: Jan 18 2011 19:25:29

Hypervisor TCP control server started (port 7100).

ismail@ismail-ThinkPad-T410:~$ ps -ef | grep dynamips
ismail   16919  8265  6 17:59 pts/2    00:00:00 dynamips -H 7100
ismail   16934  8265  0 17:59 pts/2    00:00:00 grep --color=auto dynamips
ismail@ismail-ThinkPad-T410:~$ 

"dynamips -H 7100 &" komutu ile dynamips servisini 7100 nollu porttan çalıştırıp, "&" kısmı le başlatılan bu servisi arka plana atmış oluyoruz. "ps -ef | grep dynamips" komutu ile ise, başlattığımız servisi kontrol ediyoruz. Aldığımız cevap işlern younda gittiğini gösteriyor.


2-) dynagen topoloji dosyasının oluşturulması;


# [1 nolu dynamips başlangıç]

[localhost:7100]
  udp=10000
  workingdir = /tmp/working

[[3725]]
  image = /tmp/c3725-adventerprisek9-mz.124-15.T13.bin
  ram = 128
#  idlepc = ?? Bunun hakkında daha sonra konuşacağız
  ghostios = true
  sparsemem = true
  idlemax = 100
  disk0=128

 [[Router R1]]
  model = 3725
  console = 2001
  autostart = false
#  F0/0 =
  S0/0 = R2 S0/0

 [[Router R2]]
  model = 3725
  console = 2002
  autostart = false
#  F0/0 =
  S0/0 = R1 S0/0
  S0/1 = R3 S0/0

 [[Router R3]]
  model = 3725
  console = 2003
  autostart = false
  S0/0 = R2 S0/1
# F0/0 =

# [1 nolu dynamips bitiş]

[localhost:7100] ile başlayan ilk bölüm çalışmaktan olan dynamips servisi ile bağlantı kurmak içindir. Çalışırken bazı dosyalar oluşturulacak, working dizini bu dosyaların yolunu belirliyor.


[3725] ile işaret edilen ikinci bölüm ise, hangi cisco modeli cihaz oluşturduğumuz ifade ediyor. Bu model cihazın kullandığı ios imajı ve ram gibi bazı donanımsal bilgiler de bu bölümde tanımlanmaktadır. 


Topoloji dosyaımızın son bölümü ise, sanal yönlendiricilerimizin tanımlandıkları yer. İkinci bölümde birden fazla model tanımlayabilir ve bu bölümde her bir sanal yönlendiricimiz için faklı bir model profili kullanabilirdik. Yine yönlendirici tanımlarken, konsol bağlantı port numarası, otomatik başlatılacak mı ve arabilirim (interface) bağlantıları da tanımlanmaktadır.


"working" dizinimizi /tmp aldında oluşturduktan sonratopoloji dosyamızı "/tmp/sample1.net" ismi ile kaydedip, dynagen 'i başlatıyoruz;



ismail@ismail-ThinkPad-T410:~$ vim /tmp/sample1.net
{write dynagen configuration file content as above INSTANCE1}
ismail@ismail-ThinkPad-T410:~$ 
ismail@ismail-ThinkPad-T410:~$ dynagen /tmp/sample1.net 
Reading configuration file...

Shutdown in progress...
Shutdown completed.
CPU0: carved JIT exec zone of 64 Mb into 2048 pages of 32 Kb.
NVRAM is empty, setting config register to 0x2142
C3725 instance 'ghost-c3725-adventerprisek9-mz.124-15.T13.bin-localhost.ghost' (id 3):
  VM Status  : 0
  RAM size   : 128 Mb
  NVRAM size : 128 Kb
  IOS image  : /tmp/c3725-adventerprisek9-mz.124-15.T13.bin

Loading ELF file '/tmp/c3725-adventerprisek9-mz.124-15.T13.bin'...
ELF entry point: 0x80008000

C3725 'ghost-c3725-adventerprisek9-mz.124-15.T13.bin-localhost.ghost': starting simulation (CPU0 PC=0xffffffffbfc00000), JIT enabled.

C3725 'ghost-c3725-adventerprisek9-mz.124-15.T13.bin-localhost.ghost': stopping simulation.
Network successfully loaded

Dynagen management console for Dynamips and Pemuwrapper 0.11.0
Copyright (c) 2005-2007 Greg Anuzelli, contributions Pavel Skovajsa

=> list
Name       Type       State      Server          Console   
R1         3725       stopped    localhost:7100  2001      
R2         3725       stopped    localhost:7100  2002      
R3         3725       stopped    localhost:7100  2003      
=> 
=> ?

Documented commands (type help <topic>):
========================================
capture  confreg  cpuinfo  export  hist    list  py      save   show   suspend
clear    console  end      filter  idlepc  no    reload  send   start  telnet 
conf     copy     exit     help    import  push  resume  shell  stop   ver    

=> 
=> start R1
Warning: Starting R1 with no idle-pc value
CPU0: carved JIT exec zone of 64 Mb into 2048 pages of 32 Kb.
C3725 instance 'R1' (id 0):
  VM Status  : 0
  RAM size   : 128 Mb
  NVRAM size : 128 Kb
  IOS image  : /tmp/c3725-adventerprisek9-mz.124-15.T13.bin

Loading ELF file '/tmp/c3725-adventerprisek9-mz.124-15.T13.bin'...
ELF loading skipped, using a ghost RAM file.
ELF entry point: 0x80008000

C3725 'R1': starting simulation (CPU0 PC=0xffffffffbfc00000), JIT enabled.
100-VM 'R1' started
=> 
=> start R2
Warning: Starting R2 with no idle-pc value
CPU0: carved JIT exec zone of 64 Mb into 2048 pages of 32 Kb.
NVRAM is empty, setting config register to 0x2142
C3725 instance 'R2' (id 1):
  VM Status  : 0
  RAM size   : 128 Mb
  NVRAM size : 128 Kb
  IOS image  : /tmp/c3725-adventerprisek9-mz.124-15.T13.bin

Loading ELF file '/tmp/c3725-adventerprisek9-mz.124-15.T13.bin'...
ELF loading skipped, using a ghost RAM file.
ELF entry point: 0x80008000

C3725 'R2': starting simulation (CPU0 PC=0xffffffffbfc00000), JIT enabled.
100-VM 'R2' started
=> start R3
Warning: Starting R3 with no idle-pc value
CPU0: carved JIT exec zone of 64 Mb into 2048 pages of 32 Kb.
NVRAM is empty, setting config register to 0x2142
C3725 instance 'R3' (id 2):
  VM Status  : 0
  RAM size   : 128 Mb
  NVRAM size : 128 Kb
  IOS image  : /tmp/c3725-adventerprisek9-mz.124-15.T13.bin

Loading ELF file '/tmp/c3725-adventerprisek9-mz.124-15.T13.bin'...
ELF loading skipped, using a ghost RAM file.
ELF entry point: 0x80008000

C3725 'R3': starting simulation (CPU0 PC=0xffffffffbfc00000), JIT enabled.
100-VM 'R3' started
=> 


Bir başka terminal açıp aşağıdaki komutu çalıştırdığımızda R1 yönlendiricisine erişeceğiz,



ismail@ismail-ThinkPad-T410:~$ telnet localhost 2001
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connected to Dynamips VM "R1" (ID 0, type c3725) - Console port

when press enter will appear this;

% Please answer 'yes' or 'no'.
Would you like to enter the initial configuration dialog? [yes/no]: 


Ctrl+C ile cisco'nun "initial configuration" sihirbazından çıkıyoruz;



Press RETURN to get started!


*Mar  1 00:00:03.843: %LINEPROTO-5-UPDOWN: Line protocol on Interface VoIP-Null0, changed state to up
*Mar  1 00:00:03.847: %LINEPROTO-5-UPDOWN: Line protocol on Interface IPv6-mpls, changed state to up
*Mar  1 00:00:03.927: %LINK-3-UPDOWN: Interface Serial0/0, changed state to up
*Mar  1 00:00:03.935: %LINK-3-UPDOWN: Interface Serial0/1, changed state to up
*Mar  1 00:00:04.927: %LINEPROTO-5-UPDOWN: Line protocol on Interface Serial0/0, changed state to up
*Mar  1 00:00:04.935: %LINEPROTO-5-UPDOWN: Line protocol on Interface Serial0/1, changed state to up
*Mar  1 00:00:32.927: %LINEPROTO-5-UPDOWN: Line protocol on Interface Serial0/1, changed state to down
*Mar  1 00:01:26.839: %LINEPROTO-5-UPDOWN: Line protocol on Interface Serial0/0, changed state to down
*Mar  1 00:01:32.875: %LINEPROTO-5-UPDOWN: Line protocol on Interface Serial0/0, changed state to up
*Mar  1 00:01:39.015: %LINK-5-CHANGED: Interface FastEthernet0/1, changed state to administratively down
*Mar  1 00:0
Router>1:39.075: %LINK-5-CHANGED: Interface FastEthernet0/0, changed state to administratively down
*Mar  1 00:01:40.115: %SYS-5-RESTART: System restarted --
Cisco IOS Software, 3700 Software (C3725-ADVENTERPRISEK9-M), Version 12.4(15)T13, RELEASE SOFTWARE (fc3)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2010 by Cisco Systems, Inc.
Compiled Wed 07-Apr-10 12:44 by prod_rel_team
*Mar  1 00:01:40.123: %SNMP-5-COLDSTART: SNMP agent on host Router is undergoing a cold start
*Mar  1 00:01:40.147: %LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet0/1, changed state to down
*Mar  1 00:01:40.147: %LINEPROTO-5-UPDOWN: Line protocol on Interface FastEthernet0/0, changed state to down
*Mar  1 00:01:40.159: %CRYPTO-6-ISAKMP_ON_OFF: ISAKMP is OFF
*Mar  1 00:01:40.159: %CRYPTO-6-GDOI_ON_OFF: GDOI is OFF
*Mar  1 00:01:40.951: %LINK-5-CHANGED: Interface Serial0/0, changed state to administratively down
*Mar  1 00:01:40.951: %LINK-5-CHANGED: Interface Serial0/1, changed state to administratively down
*Mar  1 00:01:41.951: %LINEPROTO-5-UPDOWN: Line protocol on Interface Serial0/0, changed state to down
*Mar  1 00:01:43.839: %IP-5-WEBINST_KILL: Terminating DNS process
Router>

2002 ve 2003 ile diğer yönlendiricilerin konsollarına da ulaşabiliriz. 

telnet localhost 2001
telnet localhost 2002
telnet localhost 2003




25 Haziran 2012 Pazartesi

Fuzuli Programlama Dilinin Kaynaktan Derlenmesi


Fuzuli Programla Dilini kaynaktan kodlardan derlemek,

http://stdioe.blogspot.com/2012/06/compiling-and-installing-fuzuli-from.html adresinde Fuzuli programlama dilinin kaynaktan nasıl derleneceğini anlatmış idim ancak bu tarif güncelliğini yitirdi. Zira Fuzuli Programlama Dili, her gün büyük gelişimler gösteren dinamik ve genç bir proje. Kaynaktan derleme işlemlerini de etkileyecek değişiklikler yapıldığından bu konuyu tekrar anlatmak gerekti.

Bir önceki makalede olduğu gibi, sürekli güncel sürümlere erişmek için kaynak koda Mercurial ile erişimi tarif edeceğim ve örnek tarif için 64 bit Ubuntu Linux işletim sistemini kullanacağım. Bunu baz alarak farklı linux dağıtımları için de benzer işlemleri yapabilirsiniz.

1-) Mercurial kurulumu ve kaynak kodlara erişim. (Install Mercurial & access source)

Not: Bu program kabaca, geliştirici / geliştiricilerin koda her yeni müdehalede bulunduklarında, her bir işleme bir açıklama bilgisi girerek ortak bir sunucuya senkronize etmelerini sağlar. Bu sayede birden fazla kişinin aynı proje üzerinde çalışmasına olanak sağladığı gibi, işler yolunda gitmediğinde ya da bir hata tespitinde zaman çizgisi üzerinde belirli bir ana dönmeyi de sağlar. 

İşte biz de bu programı kullanarak kaynak kodların bir kopyasını kendi sistemimize çekeceğiz. Aynı zamanda ilerleyen zamanlarda, yine mercurial programını kullanarak elimizdeki kaynak kodu güncelleyip tekrar derleyebileceğiz.

Mercurial programını kurmak için,

ismail@ismail-M61PME-S2P:~$ sudo apt-get install mercurial

Yukarıdaki komut marifeti ile, sistemimize mercurial kurulacaktır. Artık "hg" komutu ile mercurial'i kullanabilir durumdayız. Bizler sözbirliği yapmışcasına kaynak kodumuzu hep /usr/share/fuzuli dizini altına indiriyoruz. Bu sebeple öncelikle "/usr/share" dizinine gideceğim ve burada "hg" komutu ile kaynak kodları code.google 'dan isteyeceğim. Kodların bir kopyası bilgisayarıma gelirken fuzuli dizini de kendiliğinden oluşturulacak,

ismail@ismail-M61PME-S2P:~$ 
ismail@ismail-M61PME-S2P:~$ cd /usr/share/
ismail@ismail-M61PME-S2P:/usr/share$ sudo hg clone https://code.google.com/p/fuzuli/
destination directory: fuzuli
requesting all changes
adding changesets
adding manifests
adding file changes
added 109 changesets with 833 changes to 353 files (+1 heads)
updating to branch default
297 files updated, 0 files merged, 0 files removed, 0 files unresolved
ismail@ismail-M61PME-S2P:/usr/share$ 

2-)  Bağımlılıkları kurmak, (Install dependencies)

ismail@ismail-M61PME-S2P:/usr/share/fuzuli$ sudo apt-get install libmysqlclient-dev libgd2-xpm-dev libreadline-dev libssl-dev libncurses5-dev libfltk1.1-dev

Ve ayrıca elbette gcc, g++ derleyicilerini de kurmamız gerekecek. Derleyicimiz olmadan Fuzuli'yi derlememiz mümkün olmayacaktır.

Yukarıdaki paketler, Fuzuli Programlama dilini derlemek için gerekli bağımlılıkların development paketleridir. Fuzuli derlendikten sonra bu sistemde kullanılabilmesi için ilgili paketlerin developmen olmayan yani sonlarında "-dev" ismi olmayan paketlerinin de yüklenmesi gerekecektir.


Not: Bağımlılık paketlerinin bir kısmı dinamik, bir kısmı ise statik derlenmektedir. Bunun anlamı, statik derlenen paketlerin "dev" versiyonları dışında ayrıca kendilerine ihtiyaç duyulmayacağıdır. Zira statik olmaları Fuzuli'nin içine gömülü çalışacakları anlamına gelmektedir. Ancak dinamik derlenenler, Fuzuli'nin içine gömülü olmayacakları için ilgili paketlerin kurulmuş versiyonlarına ihtiyaç olacaktır. Bu bir detay bilgidir, ayrıca paketlerin statik, dinamik durumlarını gösterir bir liste bu makale içinde verilmemiştir.


Ayrıca çok fazla müdehale gerektirdiği ve Fuzuli kullanıcıları pek uğraştırdığı için Fuzuli'nin kaynak koduna eklediğimiz soket kütüphanesi olan happycoders'ın kaynak kodları da Fuzuli Kaynak kodları içine eklenmiştir. Şimdi bu dizine gidip, happycoders'ı derleyelim;


ismail@ismail-M61PME-S2P:/usr/share$ cd fuzuli/
ismail@ismail-M61PME-S2P:/usr/share/fuzuli$ cd lib/libsocket-1.8/
ismail@ismail-M61PME-S2P:/usr/share/fuzuli/lib/libsocket-1.8$ sudo ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking for g++... g++
checking for C++ compiler default output file name... a.out
...
...
ismail@ismail-M61PME-S2P:/usr/share/fuzuli/lib/libsocket-1.8$
ismail@ismail-M61PME-S2P:/usr/share/fuzuli/lib/libsocket-1.8$ sudo make
cd . && /bin/bash /usr/share/fuzuli/lib/libsocket-1.8/config/missing --run aclocal-1.7 
/usr/share/fuzuli/lib/libsocket-1.8/config/missing: line 46: aclocal-1.7: command not found
WARNING: `aclocal-1.7' is missing on your system.  You should only need it if
         you modified `acinclude.m4' or `configure.ac'.  You might want
         to install the `Automake' and `Perl' packages.  Grab them from
         any GNU archive site.
cd . && \
...
...
ismail@ismail-M61PME-S2P:/usr/share/fuzuli/lib/libsocket-1.8$ 
ismail@ismail-M61PME-S2P:/usr/share/fuzuli/lib/libsocket-1.8$ sudo make install
Making install in src
...
...
PATH="$PATH:/sbin" ldconfig -n /usr/local/lib/happycoders/
----------------------------------------------------------------------
Libraries have been installed in:
   /usr/local/lib/happycoders/

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,--rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
...
...
ismail@ismail-M61PME-S2P:/usr/share/fuzuli/lib/libsocket-1.8$ 

Not: Yukarıdaki kurulum çıktısında satırların uzayıp gitmelerine mani olmak için bazır önemsiz olabilecek bölümleri "..." ifadesi ile özetleyip, gizledim.

Kurulumun sonunda bir rapor bilgisi veriliyor. Buna göre happycoders kütüphanesi dosyaları "/usr/local/lib/happycoders" dizinine yüklenmişler. Ancak Fuzuli programı onları "/usr/lib/happycoders" dizini içinde arayacak. Bu sebeple mevcut dizinini "ldconfig" ile register edip, bu dizinin bir de "/usr/lib" altına link'ini oluşturacağım:

ismail@ismail-M61PME-S2P:/usr/share/fuzuli/lib/libsocket-1.8$ sudo ldconfig /usr/local/lib/happycoders/
ismail@ismail-M61PME-S2P:/usr/share/fuzuli/lib/libsocket-1.8$ sodu ln -s /usr/local/lib/happycoders /usr/lib/happycoders
ismail@ismail-M61PME-S2P:/usr/share/fuzuli/lib/libsocket-1.8$ 

Artık Fuzuli'yi derlemek için ön hazırlıklarımız tamamlanmış durumda.

3-) Fuzuli'nin derlenmesi; (compiling Fuzuli)

Bu makalede sıfırdan kulum anlatıyor olsakda bir alışkanlığın sonucu olarak tedbiren önce "clean" yapıp sonra "build" yapıyorum,

ismail@ismail-M61PME-S2P:/usr/share/fuzuli/lib/libsocket-1.8$ cd /usr/share/fuzuli/
ismail@ismail-M61PME-S2P:/usr/share/fuzuli$ sudo ./release-clean-all.sh 
ismail@ismail-M61PME-S2P:/usr/share/fuzuli$ sudo ./release-build-all.sh

Not: Yine kalabalık yaratmamak için komutların çıktılarına yer vermedim.

Bu noktada "/usr/lib/fuzuli" dizini altında fuzuli binary'si ve kütüphaneleri bulunmaktadır. fuzuli binary'sinin alışageldik yeri olan "/usr/bin" dizininde de olması gerekir. Bunun için,

a) fuzuli binary'sinin link'ini "/usr/bin" altına oluşturacağım.

ismail@ismail-M61PME-S2P:/usr/share/fuzuli$ sudo ln -s /usr/lib/fuzuli/fuzuli /usr/bin/fuzuli

Ayrıca kütüphanelerin kullanılabilir olması için

b) ya "/usr/lib" altına kopyalanmaları gerekir,


ismail@ismail-M61PME-S2P:/usr/share/fuzuli$ sudo cp /usr/lib/fuzuli/*.so /usr/lib/

b) ya da mevcut dizinleri "ldconfig" ile register edilmeli, 


ismail@ismail-M61PME-S2P:/usr/share/fuzuli$ sudo ldconfig /usr/lib/fuzuli/

Kurulan Fuzuli'nin test edilmesi; (testing Fuzuli)

Artık Fuzuli Programlama Dilimiz tam olarak kullanıma hazır. Her şeyin yolunda gittiğinden emin olmak için kaynak kodları indirdiğimiz dizin içindeki "tests" dizinine gidip, tüm testleri çalıştırabiliriz.

ismail@ismail-M61PME-S2P:/usr/share/fuzuli$ cd /usr/share/fuzuli/tests/
ismail@ismail-M61PME-S2P:/usr/share/fuzuli/tests$ ./tester.sh 
--------------------------------------------
|      testing all FUZULI script files.     |
--------------------------------------------

argc_argv.fzl:
1: PASS
arithmetic.fzl:
1: PASS
2: PASS
3: PASS
4: PASS
5: PASS
6: PASS
7: PASS
8: PASS
9: PASS
10: PASS
11: PASS
12: PASS
block.fzl:
1: PASS
Break.fzl:
1: PASS
clientsocket.fzl:
1: PASS
clone.fzl:
1: PASS
2: PASS
dotimes.fzl:
1: PASS
eval.fzl:
1: PASS
explode.fzl:
1: PASS
fibonacci.fzl:
1: PASS
2: PASS
3: PASS
4: PASS
5: PASS
for.fzl:
1: PASS
2: PASS
3: PASS
4: PASS
funcoverload.fzl:
1: PASS
2: PASS
3: PASS
hex.fzl:
1: PASS
inc.fzl:
1: PASS
2: PASS
io.fzl:
1: PASS
2: PASS
3: PASS
4: PASS
letTest1.fzl:
1: PASS
list.fzl:
1: PASS
2: PASS
3: PASS
4: PASS
5: PASS
6: PASS
7: PASS
8: PASS
math.fzl:
1: PASS
2: PASS
3: PASS
4: PASS
5: PASS
6: PASS
7: PASS
8: PASS
9: PASS
maxmin.fzl:
1: PASS
ols.fzl:
1: PASS
2: PASS
oop.fzl:
1: PASS
2: PASS
sort.fzl:
1: PASS
2: PASS
strings.fzl:
1: PASS
2: PASS
3: PASS
4: PASS
5: PASS
6: PASS
7: PASS
8: PASS
9: PASS
10: PASS
11: PASS
12: PASS
13: PASS
14: PASS
15: PASS
16: PASS
17: PASS
18: PASS
19: PASS
20: PASS
21: PASS
22: PASS
23: PASS
24: PASS
25: PASS
26: PASS
27: PASS
28: PASS
29: PASS
switchcase.fzl:
1: PASS
types.fzl:
1: PASS
2: PASS
while.fzl:
1: PASS

--------------------------------------------
|             Report of test               |
--------------------------------------------
|  26 files has been tested.
|  98 statements has been passed.
|  0 statements has been failed.
|  0 statements has been undefined.
--------------------------------------------
ismail@ismail-M61PME-S2P:/usr/share/fuzuli/tests$ 

Tüm testlerin geçtiğini gördüğümüzde herşeyin yolunda gittiğinden emin olabiliriz. Ayrıca samples/gui dizini altında Grafik Kullanıcı Arabirimi örneklerine de erişebiliriz. Örneğin,

ismail@ismail-M61PME-S2P:/usr/share/fuzuli/tests$ cd ../samples/gui/
ismail@ismail-M61PME-S2P:/usr/share/fuzuli/samples/gui$ fuzuli gui4.fzl 
[close, Hello Fuzuli GUI, 297, 296, 230, 230, @FuzuliNativeObject[@FuzuliWidget]]
Exiting...ismail@ismail-M61PME-S2P:/usr/share/fuzuli/samples/gui$ 


----
Kurulumdan daha sonraki bir tarihte Fuzuli'nin güncel kaynak kodları ile tekrar derlenmesi (update Fuzuli)


Fuzuli Programlama Dili'nin genç ve bir o kadar da dinamik bir proje olduğunu söylemiştim. Dolayısıyla her yeni bir gün, Fuzuli için yepyeni fonksiyonlar yazılmaya devam edecektir. Bu sebeple kodunuzu zaman zaman güncelleyip, Fuzuli'yi tekrar derlemeniz de gerekecektir.

Bu işlem, buraya kadar anlatılanlardan çok daha kolay olacaktır, zira tüm bağımlılıklar yüklenmiş, ilgili dizinler register edilmiş, link'ler tanımlanmış durumda. Sırasıyla,

a) Kaynak kodun güncellenmesi, (update source)

fuzuli'nin kaynak kodlarının olduğu "/usr/share/fuzuli" dizinine gidip hg ile yeni kodları istiyoruz.

ismail@ismail-M61PME-S2P:~$ cd /usr/share/fuzuli/
ismail@ismail-M61PME-S2P:/usr/share/fuzuli$ sudo hg pull
pulling from https://code.google.com/p/fuzuli/
searching for changes
no changes found
ismail@ismail-M61PME-S2P:/usr/share/fuzuli$ 

Bu makale hazırlanırken, zaten en güncel kodu indirdiğimiz için değişiklik tespit edilmedi ancak "No changes found"  yerine bir takım değişikliklerin tespit edildiğini düşünelim. Bu durumda "sudo hg update" ile değişiklikleri uygulamamız gerekecekti.

b) Ve daha sonra Fuzuli'yi önce "clean" edip sonra tekrar "build" etmeliyiz, (re-compile source)

ismail@ismail-M61PME-S2P:/usr/share/fuzuli$ sudo ./release-clean-all.sh
ismail@ismail-M61PME-S2P:/usr/share/fuzuli$ sudo ./release-build-all.sh 

Artık son güncel versiyon Fuzuli diline sahibiz.
Lütfen varsa karşılaşılan sorunlar için bilgi veriniz.

8 Mayıs 2012 Salı

PHP - GTK ile Masaüstü Uygulaması Programlama


PHP-GTK, PHP’nin masaüstü yazılım olarak geliştirilmesine katkı sağlamak için oluşturulan bir eklenti olarak yazılmıştır. Diğer masaüstü yazılımlara göre daha zahmetli uygulama olması, GTK’nin gelişmesine engel olsa da, PHP-GTK’nin online bir masaüstü yazılım olabileceği hayali, bu eklentinin rakipsiz bir yazılım olacağının habercisidir.

PHP-GTK, object-oriented programming (OOP) uygulayarak grafik arayüzlü programlar yazmayı sağlamaktadır. Bu bölümde PHP-GTK ile ilgili geniş detaya değinilecektir.

PHP-GTK Nedir?

PHP-GTK aktif PHP gelişime katkı sağlamak amacıyla oluşturulmuş bir eklentidir. Andrei Zimievski imzalı bir açık kaynak uygulamadır. Oluşturulma amacında PHP dilinin geliştirilmesi yatan bu uygulama PHP topluluğu tarafından kabul görmüştür. Fakat daha sonra bu amaçtan bir hayli çıkacaktır. İlk versiyonu 2001 Mart’ında yayımlandıktan sonra PHP-GTK’nin geliştirilmesine daha fazla yazılımcı katılmaya başlamıştır. Scintilla ve GtkHTML gibi çeşitli widgetler ile uyumlu hale getirilerek büyümesi devam ettirilmiştir.

Daha sonraki süreçte 2003 Ekim aylarında GTK 1.0 versiyonu ile tam anlamıyla açık kaynak platform dahilinde geliştirilmeye bırakılmış ve PHP toplulukları tarafından geliştirilmiştir. Bundan sonra kullanım amacı


İrdeleme Köşesi

Widget Nedir?

Görsel programlama çerçevesinde bulunan bir yazılım kütüphanesinin içerisindeki grafik bileşenlerine widget denilmiştir. Button, scrollbar, checkbox, listbox, text, textarea, radiobutton, label, fieldset gibi birçok obje, widget olarak bilinmektedir.



şekillenen PHP-GTK, PHP5 ile geliştirilen nesne yönelimli programlamayı (OOP) kod içerisine entegre etmiştir. Sürekli olarak gelişime devam eden widgetler ise PHP-GTK’nin gerçek bir masaüstü yazılım olmasına olanak sağlamıştır.

Kimilerine göre Java, C++ ya da C# varken PHP-GTK gibi yorucu ve karmaşık bir uygulama kullanmak oldukça yanlış bir yol gibi görünmekteydi. Fakat PHP bilen bir yazılımcının nesne tabanlı yazılım ile PHP-GTK geliştirmesi hiç de zor bir iş olmayacaktı.

PHP-GTK aslında bir uygulama değil, eklentidir. Yalnızca PHP5.1 ve sonraki versiyonlarda kullanılabilmektedir. Bunun sebebi PHP-GTK’nin nesne yönelimli olması ve nesne yönelimli yazılım geliştirilmesinin de PHP 5.0 sürümünden sonra geliştirilmesidir.

PHP’nin bu masaüstü yazılım eklentisi, herhangi bir web tarayıcısına ya da Apache gibi bir sunucuya ihtiyaç duymamaktadır. Çünkü PHP-GTK bir web uygulaması değil, bir masaüstü uygulaması mantığı ile geliştirilmiştir.


PHP-GTK Kurulumu (Windows İçin)

PHP-GTK kurulumu, bunun bir eklenti olması bakımından, eklentilerin kurulum kolaylıkları göz önüne alındığında, oldukça zor ve karmaşık olarak adledilmektedir. Öyle ki, PHP-GTK geliştiricileri, bu durumu “Windows sistemlerde, PHP-GTK kurulum süreci sıkıcı..” gibi bir ifadeyle belirtmektedir. Buradan hareketle Gnope PHP-GTK installer program üretilmiştir. Gnope, bir program yönetim ortamı olarak düşünülebilir. Nitekim grafik arayüzü, PHP-GTK’nin birçok platformda çalışmasına olanak sağlamaktadır.

Bunun dışında manuel kurulum da mümkün olmaktadır. gtk.php.net gtk resmi web sayfasının download bölümünden, kendi işletim sisteminize uygulan olan dosyayı indirdikten sonra kurulum işlemine başlayabiliriz.

Download edilen .rar ya da .zip formatlı kurulum dosyası açıldığında php, winnt ve test klasörleri görülecektir. C:/ sürücüsüne php klasörünü kopyalamak gerekmektedir. Bunun sebebi, yapılan gtk projelerinin bu klasör altında çalıştırılacak olmasıdır. Bu işlemden sonra test klasörü php klasörü içerisine kopyalanacaktır. Şu anda, yapılan projeler c:\php\test adresinde görüntülenmektedir.

Son bir işlem yaptıktan sonra işletim sisteminiz içerisinde PHP-GTK çalıştırabileceksiniz.

PHP-GTK kurulum dosyası
Download edilen dosya içerisinde bulunan winnt klasörünün varlığından bahsetmiştik. Bu klasör açıldığında, php.ini dosyası görülecektir. Bu dosya,  C:/ sürücüsüne kopyalanan php klasöründeki php.ini dosyası ile değiştirildiğinde artık kurulum tamamlanmış olacaktır.

Bu bölümde, Windows işletim sistemleri üzerinde PHP-GTK kurulumu anlatılmıştır. Linux ya da Mac OS X sistemlerinde kurulum yapmak için gtk.php.net/manual/en/tutorials.installation.php adresini ziyaret edebilirsiniz.

İlk GTK Projesi

Programlama dilleri ile ilgili kitaplarda genel olarak ilk proje, “Merhaba Dünya!” ya da “Hello World” ifadesi ile şekillendirilmektedir. Biz de PHP-GTK projesi için böyle bir örnek ile başlayalım. Projeyi geliştirirken, kurulumu da başarılı bir şekilde yapıp yapmadığımızı anlayabileceğiz.

İlk PHP-GTK Projesi – Merhaba Dünya


<?php
function sifirla() {
                        Gtk::main_quit();
}
$window = new GtkWindow();
$window->connect_simple('destroy','sifirla');

$window->set_border_width('50');

$label = new GtkLabel("Merhaba Dünya");
$window->add($label);

$window->show_all();
Gtk::main();
?>


Yukarıdaki kodları ilkgtkprojem.php dosya adıyla kaydedip, konsol kısmından çalıştıralım.

Program çalıştırma


Başlat/çalıştır/cmd
c:\php4\php c:\php4\test\ilkgtkprojem


Yukarıdaki komutlar yazılıp enter tuşuna basıldığında aşağıdaki görüntü elde edilecektir.

ilkgtkprojem.php
Şu an için bu kodlamayı tam anlamıyla anlamanız biraz güç olsa da bu bölümün sonunda en azından fikir sahibi olacağınızı düşünmekteyim. Buradan hareketle ilkgtkprojem.php kodlarını satırlar halinde incelemekte fayda görüyorum.

İlk PHP-GTK Projesi – destroy


function sifirla() {
                        Gtk::main_quit();
}
$window->connect_simple('destroy','sifirla');



Bu satırlar, program kapatıldığında, yeni bir komut girme işlemine izin verilmesi amacıyla yazılmıştır. Bu fonksiyon oluşturulmamış olsaydı program kapatıldıktan sonra konsol çalışmayacak ve tekrardan Başlat/çalıştır/cmd işlemini yapmak durumunda kalacaktık. Aslında destroy yöntemi, bundan önceki çalışan programı ve nesneleri yok etmek için kullanılmaktadır ve connect_simple(destroy) özelliği ile belirtilmektedir.

İlk PHP-GTK Projesi – pencere oluşturma ve özellik verme


$window = new GtkWindow();
$window->set_border_width('50');



Yeni bir pencere kutusu oluşturmak için GtkWindow() nesnesi oluşturulmaktadır.

set_border_width() fonksiyonu ile de pencerenin genişliği ayarlanmaktadır.

İlk PHP-GTK Projesi – pencere oluşturma ve özellik verme


$window->add($label);
$window->show_all();
Gtk::main();



PHP-GTK üzerine çalışma yapıyorsanız bu kodlar sayısız defa karşınıza çıkacaktır. Nitekim var olan widgetlerin sayfada gösterilmesi bu yolla olmaktadır. Program içerisinde oluşturulan her widget, kod sonunda $window->add($widget) şeklinde eklenmelidir.

PHP-GTK Üzerinde İşlem Yapmak

PHP-GTK çok geniş bir fonksiyon kütüphanesine sahiptir. Bunun sebebi geliştirilmiş birçok widget olması ve OOP yöntemi kullanılmasıdır. Önceki uygulamada vurgulanan fonksiyona benzer birçok fonksiyon daha vardır. Fakat bu kitapta bunların hepsine değinebilmek mümkün olmayacaktır. PHP-GTK’nin resmi web sayfasında tüm kütüphaneye erişmek mümkündür. Bu kitapta yalnızca en çok kullanılacak olan bazı fonksiyonları görebileceğiz.

Bazı PHP-GTK Fonksiyonları

Fonksiyon


Özellik

set_size_request(400, 100)
Genişliği 400, yüksekliği 100 birim olan bir widget
modify_bg(Gtk::STATE_NORMAL, GdkColor::parse("#FFFFFF"))
Arka plan rengi beyaz olan bir pencere
modify_font(new PangoFontDescription('Arial 48'))
Font özellikleri arial ve ölçüsü 48 pixel olan bir yazı tipi
set_justify(Gtk::JUSTIFY_RIGHT)
Yazılan metnin align=right olarak ayarlanması
set_justify(Gtk::JUSTIFY_LEFT*)
align=left ya da align=center*
set_title()
Pencere başlığı belirlenmesi
connect(‘clicked’,’’)
Butona tıklandığında devreye girecek olan komut ayarlanması


PHP-GTK eklentisinde fonksiyon ve nesnelerin varlığından bahsetmiştik. Bunun yanında bir de yöntemler vardır. Widgetler, beraberinde bazı olaylar ve yöntemler de taşımaktadırlar. Masaüstü yazılım deneyimi olanların hatırlayacağı gibi, button, clicked özelliğine sahiptir. Üzerine tıklandığında devreye giren bir komut programın akışında belirtilmiştir. PHP-GTK’de bu yönden oldukça geniş bir kütüphaneye sahiptir.
Button nesnesinin bazı yöntemleri

Yöntem


İşlevi

clicked()
Tıklama yapıldığında devreye girer
enter()
Giriş yapıldığında devreye girer
set_alignment()
Butonun bulunacağı yeri ayarlar
set_label()
Butonun metnini belirler
activate()
Widgeti aktif yapar, harekete geçirir
pressed()
Buton üzerinde Mouse ile tıklandığı zaman devreye girer
leave()
Buton üzerinden Mouse çekildiği zaman devreye girer
enter()
Mouse işaretçisi (ok) düğmeye bastığında devreye girer



PHP-GTK kütüphanesinde, Object Hierarchy (nesne hiyerarşisi) bulunmaktadır. Bunun sebebi her bir sınıfın başka bir alt sınıf oluşturması ve OOP kullanarak tam anlamı ile bir dinamizm oluşturmaktır.





GtkButton, GtkWindow, GtkFrame, GtkEventBox, GtkComboBox gibi alt sınıfların her biri teker teker incelenmeye başlanıldığında, her birinin onlarca yönteme sahip oldukları görülecektir.

Pencere Oluşturma ve Widget Yerleştirme

Bir pencere oluşturma – window.php


<?php
$window = &new GtkWindow();
$window->show_all();
Gtk::main();
?>




Bir pencere oluşturma
Yukarıda görüldüğü gibi sadece bir pencere oluşturulmuştur. Buraya boyut verilebilir.

Bir pencere üzerine buton yerleştirme – button.php


<?php
function sifirla() {
            Gtk::main_quit();
}
$window = &new GtkWindow();
$window->connect('destroy', 'sifirla');

$button = &new GtkButton('Button ismi');
$window->add($button);

$window->show_all();
Gtk::main();
?>



Bir pencere üzerine buton yerleştirme
Button bir widgettir. Widgetlerin de uygulanma yöntemleri vardır. Button için clicked yöntemi olduğundan bahsetmiştik. Bir pencere üzerine button yerleştirip, button tıklandığında clicked yönteminin devreye girmesini sağlayalım. Bunun için clicked metoduna bir fonksiyon bağlamak gerekecektir.

Buton oluşturma ve yöntem uygulama – clicked.php


<?php
function sifirla() {
            Gtk::main_quit();
}
//Clicked olayının etkileşim halinde olduğu fonksiyon
function merhaba() {
            global   $window;
            print "Sisteme girdiniz!\n";
            $window->destroy();
}
//Yeni bir pencere oluşturuyoruz.
$window = &new GtkWindow();
$window->connect('destroy', 'sifirla');
//Pencere genişliği 60 pixel olarak ayarlanıyor.
$window->set_border_width(60);
//Pencere başlığı belirleniyor.
$window->set_title("Sisteme girmek istiyorsunuz..");
//Yeni bir buton oluşturuluyor.
$button = &new GtkButton('Sisteme Giriniz..');
//Buton için clicked yöntemi uygulanıyor.
//merhaba() fonksiyonu ile bağlanıyor.
$button->connect('clicked', 'merhaba');
//Buton genişliği 10 pixel olarak ayarlanıyor.
$button->set_border_width(10);
$window->add($button);
$window->show_all();
Gtk::main();
?>



Yukarıdaki kodlar çalıştırılıp ekran görüntüsü alındığında karşımıza bir pencere üzerinde button çıkacaktır. Butona tıklandığında konsola geçilecek ve ekranda giriş yapıldığını belirten bir mesaj çıkacaktır.

Buton oluşturma ve yöntem uygulama


Sisteme Giriniz.. isimli butona tıklandığında clicked olayı merhaba() fonksiyonu devreye sokacaktır.

Buton oluşturma ve yöntem uygulama sonuç ekran görüntüsü
Web tabanlı programlama çerçevesinde veri alışverişi büyük önem taşımaktadır. Zira daha önceki konularda, link üzerinden, form alanları üzerinden ya da veritabanlarından verileri çekip üzerinde işlemler yapmıştık. Şimdi konumuz PHP-GTK ve PHP’yi masaüstü yazılım olarak kullanmaktayız. Verileri çekip, bunları işlemek ihtiyacı her zamanki gibi burada da karşımıza çıkacaktır.

Form alanlarından veri çekip bunları işleme – data.php


<?php

$window = new GtkWindow();
$window->set_size_request(280, 90);
$window->connect_simple('destroy', array('Gtk','main_quit'));
$window->set_title("input Üzerinden Value Alma");

$window->add($vbox = new GtkVBox());

$baslik = new GtkLabel("Veri Gönderimi-Value Alma\nVeri girip Enter'a Bas!");
$baslik->modify_font(new PangoFontDescription("Sans bold"));
$baslik->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#333"));
$baslik->set_size_request(0, 30);
$vbox->pack_start($baslik, 0, 0);

$hbox = new GtkHBox();
$vbox->pack_start($hbox, 10, 100);
$hbox->pack_start(new GtkLabel("Veri Giriniz."), 0, 10);
$veri = new GtkEntry();
$hbox->pack_start($veri, 0, 30);
$veri->connect('activate', 'verigir');

function verigir($obje) {
$girilen = $obje->get_text();
if (!$girilen==0 && strlen($girilen) > 3)
   echo "Girilen veri = $girilen\n";
elseif ($girilen=='')
   echo "Veri girmeniz gerekmektedir!\n";
else
   echo "En az 4 karakter girmelisiniz!\n";
    $obje->grab_focus();
}

$window->show_all();
Gtk::main();

?>


Yukarıdaki program çok basit bir form aracılığıyla veri taşıma ve işleme yöntemidir. Verilerin girileceği bir text alanı oluşturduk. Daha sonra verileri alıp ekrana yazdırdık.
Form alanlarından veri çekip bunları işleme
Yukarıdaki görüntü incelendiğinde, bir text alanı, veri girilmesini beklemektedir. Veri girişi yapıldıktan sonra enter tuşuna basıldığı an PHP-GTK if, elseif ve else koşullu durumları göz önüne alınarak ekrana veriyi yazdıracaktır. Eğer veri en az 4 karakter olarak girilirse veri ekrana echo fonksiyonu ile yazdırılacaktır. 4’ten az sayıda karakter girilip enter tuşuna basıldığında ekranda bu durum ile ilgili bir hata mesajı gösterilecektir. Hiç veri girilmemiş ve enter tuşuna yine de basılmış ise yine durumu açıklar nitelikteki hata mesajı ekrana yazdırılacaktır.

Bütün bunlar yapılırken PHP-GTK ile PHP arasında kodlama açısında hiçbir fark olmadığı, aksine tam anlamıyla PHP kodlaması yapıldığı görülmektedir. Zira if, else, elseif koşul durumları, echo fonksiyonu, OOP gibi PHP özellikleri kullanıldığı rahatlıkla görülebilmektedir.

Bu kodlamada daha önce görmediğiniz bazı yöntemler ve fonksiyonlar mevcuttur. PHP-GTK’nin geniş kütüphanesinde bulunan her bir fonksiyon gtk.php.net adresinde incelenebilir. Fakat bu program için bilinmeyenlere göz atmak yararlı olacaktır.

vbox() ve hbox() – data.php


$window->add($vbox = new GtkVBox());

$hbox = new GtkHBox();



PHP-GTK kütüphanesi incelendiğinde vbox ve hbox ifadeleri sıkça karşımıza çıkacaktır. Dikey ve Yatay kelimelerinin vertical ve horizontal olarak İngilizce’den çevirmeleri, programlama dillerinde de uygulanmaktadır. vbox() dikey olarak büyüyen, hbox() ise yatay olarak büyüyüp ölçülendirilebilen kutular oluşturmak için kullanılmaktadır.
modify_font() ve modify_fg() – data.php


$baslik = modify_font(new PangoFontDescription("Sans bold"));

$baslik->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#333"));



$baslik degiskeni ile belirlenmiş karakter katarının font özelliklerinin ayarlanması işlemi burada gerçekleştirilmiş ve kalın harfler oluşturulmuştur. Ayrıca yazı rengi #333 olarak ayarlanmıştır.

Veri alımı ve işlenmesi – data.php


// Yeni bir veri giriş (input) alanı oluşturuluyor.
$veri = new GtkEntry();

// activate yöntemine verigir() fonksiyonu ilişkilendiriliyor.
$veri->connect('activate', 'verigir');

//verigir() fonksiyonu oluşturuluyor.
function verigir($obje) {

//Form alanına girilen veri alınıyor.
$girilen = $obje->get_text();

//Girişi yapılan veri eğer boş değil ve karakter sayısı 3 den büyük ise,
//Girilen veri değeri yazdırılıyor.
//Şekil 6.4.8
if (!$girilen==0 && strlen($girilen) > 3)
   echo "Girilen veri = $girilen\n";

//Eğer veri girilmemişse, hata mesajı yazdırılıyor.
//Şekil 6.4.9
elseif ($girilen=='')
   echo "Veri girmeniz gerekmektedir!\n";

//Eğer girilen verinin karakter sayısı 4’ten küçük ise,
//Hata mesajı yazdırılıyor.
//Şekil 6.4.7
else
   echo "En az 4 karakter girmelisiniz!\n";
}


Yukarıdaki kodlar programın en önemli noktalarını oluşturmaktadır. Çünkü form alanından verilerin alınıp işlendiği kodlama buradadır.

En az 4 karakter girme hata mesajı
Hatasız veri girişi
Boş giriş yapılma hata mesajı

modify_font() ve modify_fg() – data.php


$obje->grab_focus();


Bu özellik, program çalıştırıldığında kolaylıkla görülebilecek bir olayı tetiklemektedir. Text alanına veri girip enter tuşuna basmakla birlikte konsol üzerinde bir mesaj alınmaktadır. Aynı zamanda pencere üzerinde giriş bölümü aktif olarak veri girilmesini beklemektedir. Yani text alanı aktiftir. Bunu sağlayan da grab_focus() özelliğidir.

Bazı PHP-GTK Özellikleri

Özellik


Değer


İşlev

set_position()
(Gtk::WIN_POS_CENTER)
Pencerenin ekrandaki konumunu ayarlar
set_title()
($title [string])
Pencerenin başlık bilgisini ayarlar
maximize()

Pencereyi tam ekran yapar
set_size_request()
($genislik[int],$yukseklik[int])
Pencerenin genişlik ve yükseklik ayarını yapar
set_max_width_chars()
(integer)
Örnek: (10)
Belirtilen widget üzerindeki belirtilen genişlik ölçüsü sınırlarına getirilecek olan maksimum karakter sayısını ayarlar
get_max_width_chars()
(integer)
Maksimum karakter kapasitesi
set_line_wrap()
BINARY(true[1], false[0])
Karakter katarını biçer ve pencere ölçüleri dahilinde yazdırır.
set_decorated()
BINARY(true[1], false[0])
Pencerenin kenarlarını kaldırır.
grab_focus()

Seçili text kutusunun kullanılmasını sürekli aktif yapar.
add()

Belirtilen widgeti pencereye ekler.
unmaximize()

Pencere tam ekran olarak ayarlanmamışsa, orijinal boyutlarına döndürür

Uygulamalar

Tarih bilgisini PHP-GTK ile uygulama – tarih.php


<?php
$window = new GtkWindow();
$window->connect_simple('destroy', array('Gtk', 'main_quit'));
$window->set_title("Tarih Bilgisi Göstermek");
$window->set_size_request(250,30);

$tarih = new GtkLabel(date('d/M/Y H:i:s'));

$window->add($tarih);
$window->show_all();
Gtk::main();
?>


Yukarıdaki program tarih.php dosya adı ile kaydedilmiştir. tarih.php çalıştırıldığında pencere üzerinde tarih bilgisinin yazıldığı görülecektir.

tarih.php ekran çıktısı

Border ile çerçeve yapmak – border.php


<?php
$window = &new GtkWindow();
$window->connect_simple('destroy', array( 'Gtk', 'main_quit'));
$window->set_size_request(300,150);
$window->set_title("Border ile Çerçeve Yapmak");

$vbox = new GtkVBox();

$cerceve = new GtkFrame();
$cerceve->modify_bg(Gtk::STATE_NORMAL, GdkColor::parse('#0000ff'));

$baslik = new GtkLabel('Frame ile çerçevelenmiş karakter');
$baslik->set_size_request(10,10);
$cerceve->add($baslik);
$vbox->pack_start($cerceve, 50, 25);

$yazi = new GtkLabel('Metin - Text');
$vbox->pack_start($yazi);

$window->add($vbox);
$window->show_all();
Gtk::main();
?>



Yukarıdaki program, frame ile oluşturulmuş bir alanı border (çerçeve) içerisine almaktadır. Yeni bir pencere, frame, label ve dikey bir kutu oluşturulmuştur.

border.php ekran çıktısı

Menü araç çubuğu oluşturmak – menu.php


<?php
$window = new GtkWindow();
$window->connect_simple('destroy', array('Gtk', 'main_quit'));
$window->set_size_request(300,20);
$window->set_title("Araç Çubuğu Oluşturma");
$menu = new GtkMenuBar();
$dosya = new GtkMenuItem();
$dosya->add(new GtkLabel('Dosya'));
$menu->prepend($dosya);
$duzen = new GtkMenuItem('_Düzen');
$menu->append($duzen);
$yardim = new GtkMenuItem('_Yardım');
$menu->append($yardim);
$window->add($menu);
$window->show_all();
Gtk::main();
?>



menu.php ekran çıktısı
Sistemden çıkış – quit.php


<?php
$window = new GtkWindow();
$window->connect_simple('destroy', array('Gtk', 'main_quit'));
$window->set_title("Sistemden Çıkış");
$window->set_size_request(250,30);

$buton = new GtkButton("Sistemden Çıkmak İstiyorum");

$buton->connect_simple('clicked', array('gtk', 'main_quit'));
$window->add($buton);

$window->show_all();
Gtk::main();
?>



Program çalıştırıldığında ekranda bir pencere üzerinde buton görülecektir. Bu butona tıklandığında sistemten çıkış gerçekleşecektir.

quit.php ekran çıktısı
Bu yazımızda, PHP ile masaüstü uygulamaları yapmaya değindik. Umarım işinize yarayacak bir referans kaynak olmuştur.

Bir sonraki yazıda görüşmek üzere!