Biz Tech web portal powered by vidi logo2

Razvoj aplikacija za Linux u stilu Visual Basica Istaknuto

Razvoj aplikacija za Linux u stilu Visual Basica

Iako su tijekom proteklih godina i desetljeća različite verzije Unixa i kasnije Linuxa dobro uhvatile korijene na računalima širom svijeta, stječe se dojam kako je uvijek nedostajao još onaj jedan mali koračić kako bi i među programerima Linux postao omiljen kao različite verzije Windowsa. Nešto pomoću čega bi i manje vješti programeri mogli razvijati različite vrste aplikacija bez potrebe za prevelikim poznavanjem različitih finesa operativnog sustava.

Nešto poput dobro poznatog Visual Basica u Windows svijetu. Vjerovali ili ne, takav alat već neko vrijeme dostupan je programerima (i to besplatno ako se izuzme mogućnost uplate donacije kao poticaja za budući razvoj), a "odaziva" se na ime Gambas.

Što je zapravo Gambas? Riječ je o razvojnom sustavu za pisanje različitih vrsta aplikacija koji se temelji na programskom jeziku BASIC, ali istovremeno sadrži brojne karakteristike modernih programskih jezika, kao na primjer, objektna proširenja jezika. U stvari, autori alata ističu kako je Gambas u velikoj mjeri inspiriran idejama preuzetim od programskog jezika Java, iako sama sintaksa jezika predstavlja dijalekt Basica. Prije detaljnijeg predstavljanja mogućnosti Gambasa spomenimo važnu činjenicu kako je alat konstantno u razvoju potpomognutom prilično brojnom internacionalnom ekipom programera, pa se može računati kako će biti dostupan u budućnosti. Ili drugim riječima, vjerojatnost da počnete razvijati vlastite aplikacije u alatu čije se buduće verzije više neće pojavljivati je trenutno prilično mala. A to je svakako vrlo bitno ako odlučite krenuti u nekakav ozbiljniji rad na vlastitom projektu.

Glavni dijelovi Gambasa

Gambas je sastavljen od nekoliko različitih dijelova koji prilikom razvoja i distribucije vlastite aplikacije djeluju kao skladna cjelina:

  • grafički orijentirana razvojna okolina
  • prevoditelj izvornog programskog koda
  • interpreter prevedenog koda
  • arhiver izvršnog oblika programskog koda
  • posebni modul za izvođenje Gambas skripti
  • brojnih dodatnih biblioteka za uključivanje u vlastite projekte

O grafičkoj razvojnoj okolini nećemo trošiti previše riječi. Sadrži sve uobičajene mogućnosti potrebne za brz i jednostavan razvoj vlastitih Gambas aplikacija, bez prevelikog kompliciranja s dodatnim mogućnostima kao što je to na primjer slučaj kod Eclipse. Ili drugim riječima, ako ste do sada već koristili neku od verzija Visual Basica u Windows okolini, i ovdje ćete se snalaziti kao riba u vodi. Bitno je spomenuti kako razvojna okolina uključuje automatsko predlaganje naredbi tijekom pisanja programa, što bitno pomaže i ubrzava pisanje programskog koda, te alate za pronalaženje i ispravljanje pogrešaka u kodu. Danas manje-više očekivane mogućnosti od moderne razvojne okoline. No ima tu još zanimljivijih pikanterija poput editora vlastitih ikona ili posebnog modula za upravljanje različitim vrstama podržanih baza podataka.

Modul za prevođenje izvornog koda u izvršni djeluje također na uobičajeni način za moderne razvoje alate. Prevođenje izvornog koda ne izvodi se "do kraja", to jest u oblik pogodan za izravno izvođenje na procesoru, nego u poseban oblik "međukoda", čije izvođenje nakon toga preuzima interpreterski dio Gambasa. Prema tvrdnjama autora prevođenje se odvija izuzetno brzo – više stotina tisuća naredbi u sekundi, ali se pri tome ne izvodi nikakva optimizacija. Za optimizaciju prilikom izvođenja aplikacije zadužen je interpreterski dio.

Interpreterski dio Gambasa izvodi međukod nastao prevođenjem izvornog Basic koda. Budući da se kod prevođenja koda, kao što smo već spomenuli, ne izvodi nikakva optimizacija,  interpreterski dio odrađuje stvari poput učitavanja pojedinih klasa programskog koda tek kad su one zaista potrebne u programu, međusobno povezivanje klasa te druge slične stvari neophodne za brzo pokretanje i izvođenje aplikacije napisane u Gambasu. Interpreterski dio je za današnje pojmove relativno mali pa na 64 bitnim sustavima ima veličinu od oko 320 KB!

Arhiver je zadužen za pripremu izvršne verzije vlastite aplikacije za distribuciju na druga računala, što osim prevedenog programskog koda uključuje i različite dodatne biblioteke potrebne za normalno izvođenje aplikacije.

Premda je Gambas prije svega namijenjen za razvoj i distribuciju vlastitih aplikacija na Linux platformi, zanimljivo je da ga možete koristiti na sasvim drugačiji način – kao skriptno orijentirani jezik za izvođenje različitih sistemskih operacija u okviru operativnog sustava. U ovom slučaju Basic naredbe upisane u običnu tekstualnu datoteku izvodi poseban modul (scripter). Na taj način uz pomoć Gambasa možete izvoditi prilično složene administrativne operacije u operativnom sustavu, bez potrebe za poznavanjem naredbi operativnog sustava na razini dobrog administratora. Kako to izgleda najlakše je demonstrirati na primjeru iz prateće dokumentacije koji pokazuje korištenje memorije za različite aktivne procese.

Function GetUsedMemory() AS Integer

  Dim sRes As String
  Dim aRes As String[]
  Dim cVal As New Collection
  Dim sVal As String

  Exec ["cat", "/proc/meminfo"] To sRes

  For Each sVal In Split(sRes, "\n", "", True)
    aRes = Split(sVal, " ", "", True)
    cVal[Left$(aRes[0], -1)] = CInt(aRes[1])
  Next

  Return cVal!MemTotal - cVal!MemFree - cVal!Buffers - cVal!Cached + cVal!SwapTotal - cVal!SwapFree - cVal!SwapCached

End

Print Subst("Used memory: &1 Kb", GetUsedMemory())

Slika02

Programski jezik i biblioteke

Ugrađeni dijalekt programskog jezika Basic sadrži sve standardne dijelove modernih programskih jezika kao što su podrška za različite oblike struktura za ponavljanje i uvjetno izvođenje dijelova programskog koda, obradu pogrešaka ili mogućnost pozivanja različitih funkcija iz vanjskih biblioteka, ali i različite mogućnosti u prilogođavanju vlastitih aplikacija za internacionalnu distribuciju (UTF-8 podrška, mogućnost prevođenja vlastite aplikacije i ostalo).

U Gambas je također ugrađena podrška za brojne paradigme objektno orijentiranog razvoja aplikacija kao što su mogućnost kreiranja, korištenja te nasljeđivanja klasa i objekata, odnosno njihovih svojstava, događaja i metoda i tako dalje.

Jedna od najzanimljivijih mogućnosti Gambasa odnosi se korištenje dodatnih komponenti potrebnih za pristup različitim dijelovima operativnog sustava (QT4 toolkit ili GTK+ toolkit), bazama podataka (MySQL, PostgreSQL, SQLite i ODBC), različitim protokolima korištenim na razini operativnog sustava (HTTP, FTP, SMTP) i slično. Takve komponente mogu biti  pripremljene u programskim jezicima C ili C++ (priložen izvorni kod), ali i u samom Gambasu. Naravno za prvi tip komponenti morate biti malo iskusniji Linux programer (treba li vam onda uopće Gambas), dok druge predstavljaju standardne Gambas projekte, koji se po potrebi pozivaju iz novog Gambas projekta.

Evo i poslastice. Malo prije spomenuto je kako Gambas podržava rad s nekoliko različitih sustava za upravljanje bazama podataka. Obično se u različitim implementacijama drugih programskih jezika za pristup svakoj vrsti baze koriste posebne biblioteke karakteristične za tu verziju baze. Kod Gambasa je cijela stvar bitno pojednostavljena – za pristup svim vrstama baza koristi se jedinstvene API funkcije što znači da je prebacivanje između korištenja različitih baza podataka trivijalno u odnosu na neke druge razvojne alate.

Treba li mi to uopće?

Prije nego što navedeno nekoliko karakterističkih primjera programskog koda, da bi stekli uvid u to kako se određene stvari rješavaju u Gambasu, odgovorimo na najvažnije pitanje – treba li mi to uopće? Ako ostavimo po strani čisto intelektualnu znatiželju u upoznavanju novog razvojnog sustava, ili ideju o razvoju ozbiljnije aplikacije za Linux platformu (da ne zaboravimo spomenuti  trenutno podržane platforme: Archlinux, Debian, Fedora, Mandriva, SuSE, Slackware,  Ubuntu)  za globalno tržište, autor teksta će spomenuti slučaj koji mu se već dva puta dogodio u programerskoj praksi.

U oba slučaja korisnik je zahtijevao izradu relativno jednostavnog  programa, koji je trebao preko specijaliziranog korisničkog sučelja (moj dio posla) na standardnom desktop računalu upravljati posebno projektiranim hardverskim uređajem od strane samog korisnika. Naravno, rok za izradu je bio “jučer” (dakle čim prije), što znači da nije bilo vremena za upoznavanje nekih bitno različitih alata za razvoj od onih koje sam već poznavao. U budžetu projekta bila su planirana sredstva potrebna za razvoj i proizvodnju specijaliziranih hardverskih uređaja te nabavku većeg broja računala potrebnih za nadzor nad uređajima. Preostalo je još samo da se dogovorimo oko cijene izrade softvera na strani računala. I gdje je nastao glavni problem? Cijenu koju sam predložio za izradu softvera korisnik bi također prihvatio, ali sam onda spomenuo da za svako računalo (ako želimo sve raditi legalno), treba nabaviti odgovarajuću licencu Windowsa. I kad je korisnik pomnožio cijenu licence u jednom slučaju s 20, a u drugom sa najmanje 100, sve skupa je palo u vodu. Ni jedan od potencijalna dva korisnika nije želio potrošiti tolika dodatna sredstva za Windowse, koji bi bili korišteni isključivo zato da se na njima izvodi moja Windows aplikacija.

E da sam tada bar znao za Gambas te mogao predložiti razvoj aplikacije za neku od podržanih, besplatnih verzija Linuxa, jer se doista nije radilo o složenim zahtjevima! Ali sad bar znam rješenje za slijedeću takvu priliku, ako se pojavi. A možda nešto slično zatreba i vama!

Nekoliko karakterističnih primjera u Gambasu

1. Primjer koda koji vraća distribuciju Linuxa na kojem se izvodi program

Static Private Sub GetDistribution() As String

  Dim cDist As Collection = ["lsb-release": "/etc/lsb-release", "vector": "/etc/vector-version", "slackware": "/etc/slackware-version", "debian": "/etc/debian_version",
    "redhat": "/etc/redhat-release", "arch": "/etc/arch-release", "SuSE": "/etc/os-release", "gentoo": "/etc/gentoo-release", "conectiva": "/etc/conectiva-release",
    "mandriva": "/etc/mandriva-release", "pardus": "/etc/pardus-release", "kanotix": "/etc/kanotix-release"]
  Dim sPath As String
  Dim sDistro As String
  Dim cData As Collection
  Dim iPos As Integer

  For Each sPath In cDist
    sDistro = cDist.Key

    If Not Exist(sPath) Then Continue

    If sDistro = "lsb-release" Then
      cData = ReadLsbRelease(sPath)
      sDistro = cData["DISTRIB_DESCRIPTION"]
      If sDistro Then Return sDistro
      Return cData["DISTRIB_ID"] & " " & cData["DISTRIB_RELEASE"]
    Else
      Return sDistro & " " & Trim(File.Load(sPath))
    Endif
    
  Next
 
  If Exist("/etc/issue") Then
     sDistro = File.Load("/etc/issue")
     If sDistro Then
        iPos = InStr(sDistro, "\\")
        If iPos Then sDistro = Left(sDistro, iPos - 1)
     Endif
  Else
     Exec ["uname", "-s"] To sDistro
  Endif
  Return Trim(sDistro)

End

2. Primjer dijela koda Gambas komponente za rukovanje tablicama u MySQL bazi podataka

Slika06

' Gambas class file

Export
Create Static

Private $hMaintenance As _TableMaintenance
Property Read Maintenance As _TableMaintenance

Public Procedure Modify(Table As String, Optional Database As String = modMain.$Connection.Name, Optional Engine As String = modMain.$Connection.MySQL.Engine, Optional Charset As String = modMain.$Connection.MySQL.Charset)

  modMain.$Query = "ALTER TABLE `" & Database & "`.`" & Table & "`"
  modMain.$Query &= " ENGINE = " & Engine
  modMain.$Query &= " CHARACTER SET = " & Charset
  modMain.RunQuery(modMain.$Query)

End

Public Procedure ModifyColumn(Table As String, Action As String, Optional Symbol As String, Optional Definition As String, Optional Database As String = modMain.$Connection.Name)

  Action = Upper(Action)
  modMain.$Query = "ALTER TABLE `" & Database & "`.`" & Table & "` "
  Select (Action)
    Case "DROP"
      modMain.$Query &= Action & " COLUMN `" & Symbol & "` "
    Case "ADD", "MODIFY", "CHANGE", "ALTER"
      modMain.$Query &= Action & " COLUMN `" & Symbol & "` " & Definition
    Case "CHARACTER SET"
      modMain.$Query &= "CONVERT TO CHARACTER SET " & Definition
    Case "ENGINE"
      modMain.$Query &= "ENGINE " & Definition
    Default
      Error.Raise("Invalid Action")
  End Select
  modMain.RunQuery(modMain.$Query)

End

Public Procedure Add(Table As String, Optional Engine As String = modMain.$Connection.MySQL.Engine, Optional Charset As String = modMain.$Connection.MySQL.Charset, Optional Database As String = modMain.$Connection.Name)

  'Make the table statement
  modMain.$Query = "CREATE TABLE `" & Database & "`.`" & Table & "` ("
  modMain.$Query &= modMain.ArrayToString(modMain.$FieldDefinition, False)
  If modMain.$PrimaryKey Then modMain.$Query &= modMain.$PrimaryKey
  If modMain.$Index.Count Then modMain.$Query &= ", " & modMain.ArrayToString(modMain.$Index, False)
  If modMain.$ForeignKey.Count Then modMain.$Query &= ", " & modMain.ArrayToString(modMain.$ForeignKey, False)
  modMain.$Query &= ") ENGINE = " & Engine & " DEFAULT CHARSET = " & Charset

  'Clears all the information from this table to be ready for the next one
  modMain.$FieldDefinition.Clear()
  modMain.$PrimaryKey = Null
  modMain.$ForeignKey.Clear()
  modMain.$Index.Clear()

  'Runs the query
  modMain.RunQuery(modMain.$Query)

End

3. Primjer dijela koda Gambas komponente za crtanje grafikona

Slika07

Public Sub Draw()
  Dim iClientHeight, iClientWidth As Integer
 
  Dim iTitleHeight As Integer
  Dim iStaticSpace As Integer
  'Draw.Font.Size = 12 * (Chart.Width / 640)
 
  _fProportionnal = IIf(Me.Width <= Me.Height, Me.Width / (Desktop.Height * 2 / 3), Me.Height / (Desktop.Height * 2 / 3))
  If Not $bProportionnal Then _fProportionnal = 1.0
  iStaticSpace = 5 * Me._fProportionnal
  'Draw the Legend and get the graph caneva size
  $oLegend.Draw($bLegendSeries)
  'Draw The Title
  iTitleHeight = iStaticSpace
  If Not IsNull(Me.Title.Text) And Me.Title.Visible Then
 
    'Draw.Font.Grade = 4
    Draw.Font = $oTitle.Font
    Draw.Font.Size = $oTitle.Font.Size * _fProportionnal
    iTitleHeight = Draw.Font.Height * 2
  Endif

  iClientWidth = Me.Width - $oLegend._Width - 2 * iStaticSpace
  iClientHeight = Me.Height - $oLegend._Height - 2 * iStaticSpace
 
 
  Draw.FillColor = color.White
  If $iBorder Then Draw.Rect(iStaticSpace, iStaticSpace, iClientWidth - iStaticSpace, iClientHeight - iStaticSpace)
  'Draw.Font.Grade = 4
 
  $oGraphStyle.Draw(iStaticSpace, iTitleHeight, iClientWidth, iClientHeight - iTitleHeight - iStaticSpace)
 
 
  If Not IsNull(Me.Title.Text) And Me.Title.Visible Then
    Draw.ForeGround = Color.Black
    Draw.Font.Size = Me.Title.Font.Size * _fProportionnal
    Draw.Text(Me.Title.Text, iStaticSpace, iStaticSpace, iClientWidth, iTitleHeight, Align.Center)
  Endif
End

Nenad Crnko

Izvor: Vidi 245/246

Za ovaj i brojne druge korisne i zanimljive sadržaje potražite tiskano izdanje časopisa Vidi, dostupnog na svim kioscima.

na vrh članka

Više...

  • 1
  • 2
  • 3
Prev Next