1- Giriş
Yazılım geliştirirken sıklıkla karşılaştığımız bir durum şudur:

  1. Müşterinizin bir uygulama ile ilgili bazı talepleri olur.
  2. Siz bu talepleri alır, inceler ve bir SRS belgesi oluşturursunuz.
  3. Akabinde de müşterinizle anlaşıp çalışmalara başlarsınız.
  4. Siz yazılımı geliştirirsiniz, müşterinizin sistemlerine kurarsınız ve müşteriniz çok beğenir.
  5. 3 ay sonra müşteriniz “program akışı şöyle değil de böyle olsa” gibi bir talepte bulunur.
  6. Siz de kodunuzu tekrardan açıp, düzenleyip, derleyip, kurulumu tekrarlarsınız.

Yukarıdaki senaryo yazılım geliştiriciler için oldukça zorludur. Çünkü birçok müşterinin farklı ürünü ile bir yandan uğraşırken, bir yandan da eski yazılımların akış veya basit güncellemeleri ile ilgilenmek gerekmektedir.

Yazılımlar da genellikle statik olduğundan, yazılımın davranışının değişebilmesi için tekrardan kodlanması, derlenmesi ve müşteri sistemlerine kurulması gerekmektedir.

Özellikle çok müşteriniz ve çok farklı yazılımlarınız varsa bu durum sürdürülebilir bir halden çıkacaktır.

Çözümü var mıdır? Birçok çözümü var, fakat alternatif bir çözüm Lua gibi bir script dilini entegre ederek yazılımınızı geliştirmek olacaktır. Lua gibi bir script dilini C# programınızda kullanmanın avantajları şu şekildedir:

  • Daha deneyimsiz yazılımcılar sadece basit Lua scriptlerini editleyerek yazılımı kullanabilir
  • İş Akışı ile programlama alt yapısı birbirinden tamamen ayrılarak genelde değişecek kısım olaran iş akışı tamamen scriptler aracılığıyla dinamik olarak yapılabilir
  • Scriptler program tarafından uzaktan güncellenebilir ve bunun için basit bir dosya indirme özelliği yeterlidir

Dezavantajlar, yada daha doğrusu ek zorluklar, şunlardır:

  • Yazılım geliştirilirken başta biraz daha fazla düşünüp iyi bir mimari tasarlamak gerekir
  • C# bileşenleri daha genel geçer ve “motor” şeklinde tasarlanır
  • Bazı basit “düğmeye basılınca şu metodu çalıştır” gibi C# kodları fazlaca karmaşıklaşır

Fakat bir yazılım ürününün yaşam döngüsü düşünüldüğünde, başta bu yatırımı yapmak, sonradan yapmamanın bedelini ödemekten genelde daha mantıklı olabilir, duruma göre değişir tabii ki.

2- Kurulum
Bu yazıdaki adımları takip edebilmek için:

  1. Visual Studio C# Geliştirme Ortamı
  2. NLua Nuget Paketi

bileşenlerini kurmanız gerekmektedir. Akabinde standart bir C# Windows Form projesi açıp ekrana birkaç Button ve Label ekleyebilirsiniz.

3- Kullanım
En basit örnek şu şekilde olabilir:

// Lua scriptleme nesnesi oluştur
Lua script = new Lua();

// X ve Y adında 2 değişken script nesnesinde tanımla ve textBox'lardan sayısal değerleri ata
script["x"] = int.Parse(textBox1.Text);
script["y"] = int.Parse(textBox2.Text);

// Hesaplamayı çalıştır ve sonucu textBox'a yazdır
textBox3.Text = (script.DoString("return x*y")[0] as double?).ToString();

Bu örnekte x ve y adında 2 adet Lua değişkeni tanımlayıp ilk değerlerini atıyoruz. Sonrasında ise “return x*y” Lua scriptini çalıştırıp çıktısını yazdırıyoruz.

Biraz daha karmaşık bir örnek görelim:

// Lua scriptleme nesnesi oluştur
Lua script = new Lua();

// Gerçek bir Lua fonksiyonunu script nesnemize ekleyelim
script.DoString(@"
                function complexAdder(val1, val2)
                    return val1 + val2
                end
");

// Fonksiyonumuzu çekelim
var scriptFunction = script["complexAdder"] as LuaFunction;

// Fonksiyonumuzu kullanarak Lua fonksiyonunu çağıralım ve sonucu yazdıralım
textBox3.Text = (scriptFunction.Call(5, 777).First()).ToString();

Bu örnekte ise gerçek bir Lua fonksiyonunu dinamik olarak çağırıp 5 ile 777‘nin nasıl toplanabildiğini görüyoruz.

Şimdi daha ilginç örneklere geçiyoruz. Öncelikle “test.lua” adında bir yazı dosyası oluşturup Debug klasörümüze koyalım. Dosyanın içeriği şöyle olabilir:

function complexAdder(val1, val2)
    return val1 + val2
end

Akabinde C# projemizde şu kod bloğunu deneyelim:

// Lua scriptleme nesnesi oluştur
Lua script = new Lua();

// Dosyadan Lua scripti oku
script.DoFile("test.lua");

// Script içerisindeki fonksiyonumuzu çekelim
var scriptFunction = script["complexAdder"] as LuaFunction;

// Fonksiyonumuzu kullanarak Lua fonksiyonunu çağıralım ve sonucu yazdıralım
textBox3.Text = (scriptFunction.Call(5, 777).First()).ToString();

Şimdi kodumuzu derleyelim ve çalıştıralım. Çalıştırdığımızda 5+777 işleminin yapılıp 782 sonucunu aldığımızı göreceğiz. Akabinde kodumuzu tekrar derlemeden sadece test.lua scriptimizi şu şekilde değiştirelim:

function complexAdder(val1, val2)
    return val1 - val2
end

Kodumuzu tekrardan çalıştıralım. Sonuç olarak şimdi -772 olduğunu göreceğiz. Kodumuzu derlemeden, sadece scriptimizi değiştirerek dinamik bir biçimde yazılımımızın davranışlarını değiştirebilmeyi başardık.

Biliyorum, aklınıza birçok kullanım yeri geldi. Ama aklınıza şu soru da geldi: “Sayılarla oynamak güzel, ama gerçek C# nesnelerini nasıl scriptleyeceğiz?”. Çok zor değil, aşağıdaki C# kodunu deneyelim:

// Lua scriptleme nesnesi oluştur
Lua script = new Lua();

// Dosyadan Lua scriptini çalıştır ve çıktısını ekrana yazdır
textBox3.Text = script.DoFile("test2.lua")[0].ToString();</code>

test2.lua scriptiniz ise şu satırları içersin:

-- Gerekli bilesenleri yukle
luanet.load_assembly("System")
WebClient=luanet.import_type("System.Net.WebClient")

-- Bir istemci olustur
istemci = WebClient()

-- scozturk.com içeriğini çek ve döndür
return istemci:DownloadString('http://www.scozturk.com')

C# kodumuzu derleyip çalıştıralım. .Net WebClient nesnesini kullanarak scozturk.com‘un içeriğini alıp döndürebildik.

Peki Lua scriptimizden, C# yazılımımızdaki nesneleri nasıl kontrol edebilir? Şu kod bloğunu deneyelim:

// Bir nesne tanımlayalım
string degiskenim = "Merhaba ";

// Lua scriptleme nesnesi oluştur
Lua script = new Lua();

// Tanımladığımız nesneyi Lua scriptimizde global nesne olarak tanımlayalım
script["globalDegisken"] = degiskenim;

// Dosyadan Lua scriptini çalıştır
script.DoFile("test3.lua");

// Nesnemi güncelle
degiskenim = script["globalDegisken"].ToString();

// Ekranda göster
extBox3.Text = degiskenim;

test3.lua scriptiniz de basitçe şu satırı içersin:

globalDegisken = globalDegisken.."Dünya!"

Kodumuzu derleyip çalıştıralım, ekranda “Merhaba Dünya!” yazısını görebileceğiz. String ile işlem yapmayı saymıyoruz, daha karmaşık bir nesne ile örnek isteriz dediniz:

// Bir nesne tanımlayalım
WebClient internetNesnem = new WebClient();

// Lua scriptleme nesnesi oluştur
Lua script = new Lua();

// Tanımladığımız nesneyi Lua scriptimizde global nesne olarak tanımlayalım
script["internetNesnesi"] = internetNesnem;

// Dosyadan Lua scriptini çalıştır
script.DoFile("test4.lua");

// Nesnemi güncelle
internetNesnem = (WebClient)script["internetNesnesi"];

// Scriptin kullandığı nesneden cevap başlıklarını çek ve göster
textBox3.Text = internetNesnem.ResponseHeaders.ToString();

test4.lua scriptimiz de şu şekilde olsun:

-- Gerekli bilesenleri yukle
luanet.load_assembly("System")
WebClient=luanet.import_type("System.Net.WebClient")

-- Scozturk.com içeriğini çek ve döndür
return internetNesnesi:DownloadString('http://www.scozturk.com')

Bu son örnekte ise www.scozturk.com sitesine gidip verileri çekme işini Lua’dan yaptık. Fakat nesnemizi C#’da oluşturmuştuk. Lua scripti çalıştıktan sonra C#’dan o nesne üzerinde ek işlemler yaptık (ResponseHeaders bilgisi almak) ve nesnemizi Lua ve C# arasında nasıl kullanabileceğimizi gördük.

4- Sonuç
Lua scriptlerini en basit şekliyle C# yazılımlarından kullanmayı gördük. Daha detaylı ve mümkünse tam entegrasyon sağlanan bir örneği de bir sonraki yazımda göstereceğim.

Bu tarz programlama şekilleri birçok uygulamada gerçekte kullanılmaktadır. Uygulama alanlarından en bilindik olanı bilgisayar oyunları, sonrasında ise mühendislik yazılımlarıdır.

Bilgisayar oyunlarında genel olarak sahnelerin yürütülmesi ve oyun nesnelerinin hareketleri (çok yüksek performans gerektirmediğinden ve oyun yapılırken sık sık değişeceğinden) scriptler ile çözülürken asıl önemli işler (ekrana modelin render edilmesi, multiplayer özellikler, vb..) gerçek programlama diliyle halledilir.

Mühendislik yazılımlarında ise genel olarak mühendisin parametrik olarak ekrandan girdiği değerlerin, arka plandaki nümerik motorlara aktarılması ve ön işlemlere tabi tutulması scriptler ile yapılmaktadır.

Scriptler ile program geliştirmek için tek alternatif Lua değildir. Örneğin mühendislik yazılımlarında sıklıkla TCL kullanılır. Web tarayıcılar ise bildiğiniz gibi Javascript’i kullanmaktadır. Daha yaygın bir örnek ise genel Linux yazılımlarında bash scriptlerin yazılımlardan doğrudan kullanılması olabilir. Buna ek olarak aslında birçok script dili, birçok programlama dili ile entegre edilebilir. C# ile Lua entegrasyonu için gereken bileşenler hali hazırda kodlanmış ve NLua kütüphanesi tarafından sunulduğundan örneklerde Lua tercih edilmiştir.

Umarım yazımda geçen bilgiler işinize yarar, iyi kodlamalar.