Ubuntu altında D ile Elektronik Hobi dersleri

Başlatan elektronikhobi, 30 Ocak 2012, 01:39:52

elektronikhobi

D ile ubuntu altında elektronik hobi dersleri yazmaya başladım. Henüz bitmedi ve bu adres değişebilir ama şimdilik buradan takip edebilirsiniz.

http://www.ehobi.org/ledyakma.html

Github sayfası da burası:

https://github.com/erdemoncel/elektronikhobi

Tagli

Belki yanlış bir soru olacak ama sormadan geçemeyeceğim: Neden D? Bize ne gibi avantajlar sağlar? Kısaca değinirseniz sevinirim.

Program biraz assembly'e kaçmış gibi gözüküyor. D bilmiyorum ama şöyle bir göz atınca fiziksel adres tanımlamaları ve assembly komutları gördüm. Ayrıca "extern (C)" ifadesi sanki C kodu çağırıyor gibi. Yanılıyor muyum? O zaman yukarıdaki soruyu tekrarlamam gerekiyor: Neden D?

C kullanarak seri port erişimini "termios" kullanarak yapıyorum (yine Linux'ta). İlk kurulumu insanların C#'ta (daha doğrusu .net diyelim) alıştığı gibi kolay olmasa da donanım adresi tanımlama ve assembly komutu kullanma gibi şeyler gerektirmiyor.

Yanlış anlaşılmasın, amacım yeni bir dil tartışması başlatmak değil, forumda yeterince var zaten. D'ye karşı falan da değilim, zaten bilmiyorum ki nasıl karşı olayım? Sadece programın bu şekli hoşuma gitmedi, nasıl desem, çok standart dışı gibi geldi. Yazdıklarımın en başında sorduğum sorunun da sebebi buydu.

Ve evet, belki de en başta yazmam gereken şeyi en sonda yazıyorum: Çalışmanızı paylaştığınız için teşekkürler. Umarım merakım yanlış anlaşılmaz.
Gökçe Tağlıoğlu

bocek

Andreu Alexandrescu'nun "Neden D?" isimli makalesinin Ali Çehreli çevirisi:

http://acehreli.org/turkce_D/D_Neden.html
1 ya da 0. işte 'bit'ün mesele..

elektronikhobi

Alıntı yapılan: Tagli - 30 Ocak 2012, 08:25:35
Belki yanlış bir soru olacak ama sormadan geçemeyeceğim: Neden D? Bize ne gibi avantajlar sağlar? Kısaca değinirseniz sevinirim.

Herşeyden önce D bir sistem programlama dili. Bu konuda Scott Meyers'ın The D Programming Language kitabında bir giriş yazısı var. Aslında bu bölümü çevirebilseydik çok süper olurdu  ;-)  Oradaki görüşleri kısaca özetlersek:

C++ gerçekten çok başarılı bir dil oldu ama gözardı edilemeyecek bir gerçek var ki C++ karmaşık bir dil. Bu karmaşıklık C++'nin geniş tabanlı kullanıma sahip iki takipçisi C# ve Java'nın tasarımını da etkiledi. Her ikisi de C++'nin karmaşıklığından uzak durarak - sağladığı işlevselliği kolay kullanılabilir bir şekilde sağlamaya çalıştılar. Eğer hızlı bir şekilde kod üretmek istiyorsanız Java ve C#, C++'ye göre daha iyi bir seçim olabilir.

Fakat C++ sadece üretken bir dil olarak tasarlanmadı; C++ bir sistem programlama dili. Yani C++'nin tasarım amaçlarından bir tanesi C'ye bu yönde rakip olmak. Burada sistem programlama derken donanımla haberleşmek, gömülü sistemler ve sürücüler yazmak, kısacası üzerinde çalıştığı donanımın son damla performansını kullanacak şekilde tasarlandığını düşünebiliriz. Örneğin bir sistem programlama dili ile bir işletim sistemi yazılabilir.

D ise bu noktada sistem programlama konusunda C++'nin yeni nesil geleceği olarak düşünebiliriz. Java ve C# gibi C++'nin karmaşıklığından mümkün olduğu kadar uzak bir dil. Bellek yönetimi konusunda çöp toplama mekanizması var ama eğer isterseniz belleği kendiniz de yönetebiliyorsunuz. Örneğin C++ Unicode desteği vermiyor ama D daha başlangıçtan Unicode desteği veriyor. Bu da demek oluyor ki değişken isimlerini D'de kendi dilinizde kullanabiliyorsunuz. C++00x sadece çok kısıtlı olarak Unicode desteği veriyor.  C++ çok karmaşık ve güçlü bir dilken, D en az C++ kadar güçlü ve daha az karmaşık bir dil olarak karşımıza çıkıyor.

Kısaca diyebiliriz ki D, C++'daki boşlukları tespit edip o boşlukları dolduran, yeni, yazım açısından daha basit bir sistem programlama dili olarak karşımıza çıkıyor. Bir sistem programlama dili olduğu için bir işletim sistemi bile yazmak mümkün.

Bir de Andrei Alexandrescu diğer dillerle karşılaştırmasını yaptığı bir sahra çölü haritası mı ? ! öyle bir resim üzerinde diğer dillerle karşılaştırmasını yaptığı ilginç bir videosu var:

http://www.youtube.com/watch?v=RlVpPstLPEc

Arkadaşın bağlantısını verdiği Andrei Alexandrescu'nun yazdığı Neden D isimli makalesinde benim çok beğendiğim bir bölüm var:

D'nin çok paradigmalı multi paradigm olduğunu söylerken, bazı seçimler sırasında çatışmaların gerekmeyebileceğini kastediyoruz. D bu konuyu kavramıştır... Herşeyin nesne, fonksiyon, liste, eşleme tablosu, veya Noel Baba olması gerekmez. Ne oldukları size kalmış olmalıdır. Bu yüzden D programcılığı özgürlükler getirir, çünkü bir sorunu çözmeye çalışırken eldeki olanakları o çözüme uydurmak için çabalamak gerekmez. Buradaki bir gerçeği de dile getirmek gerekiyor: özgürlüklerle birlikte sorumluluklar da gelir; bu sefer de çözüm için hangi tasarımın daha uygun olacağına karar vermek için zaman harcamak gerekecektir.

D bu konuda C++'nın izinden yürür; doğru olan tek yol gibi bir ısrarı yoktur.


Örneğin D isterseniz çöp toplama düzeneğini kullanan otomatik bellek yönetimini kullanacağınız gibi isterseniz bellek yönetimini elle yapmanıza izin verir. Bir program derlenirken @safe @trusted @system seçenekleri ile derleme seçenekleri vardır. Örneğin @system seçeneğinde belleği elle yönetmek, bir dizinin sınırlarının dışındaki bir noktaya erişim sağlamak gibi alt düzey işlemler yapabilirsiniz. Bu durumda D ne yaptığınızı bildiğinizi varsayar.

Pratik olarak uygulamasına gelince örneğin ben LCD panele Türkçe karakterleri böyle basitçe yazdırabiliyorum:

string mesaj = "Türkçe yazıyorum";
	foreach (wchar harf; mesaj) {
		veriGönder(cast(ubyte)(harf);
	}


Alıntı yapılan: Tagli - 30 Ocak 2012, 08:25:35
Program biraz assembly'e kaçmış gibi gözüküyor. D bilmiyorum ama şöyle bir göz atınca fiziksel adres tanımlamaları ve assembly komutları gördüm.

Aslında oradaki assembly kodları C'nin sys/io.h başlık dosyasında tanımlı outb işlevinin kodları.

static __inline void outb (unsigned char value, unsigned short int port)
{
    __asm__ __volatile__ ("outb %b0,%w1"
                          :
                          :
                          "a" (value),
                          "Nd" (port));
}


Yani outb işlevinin D için yazılmış ilmeğinin kaynak kodu. Ama aslında o assembly komutlarının hiç birini ya da outb C işlevini kullanmıyor.

https://github.com/erdemoncel/elektronikhobi/blob/master/giri%C5%9F%C3%A7%C4%B1k%C4%B1%C5%9F.d

Dikkat ederseniz yorum haline getirilmiş. Onun yerine core.bitop içinde bulunan outp işlevini kullanıyor.

https://github.com/D-Programming-Language/druntime/blob/master/src/core/bitop.d

Bence bu çok güzel bir özellik. Çünkü kullanacağınız her kütüphaneyi en baştan yazmak büyük bir emek ve zaman ister.  Hatta bazılarını sil baştan yazamayabilirsiniz de. Örneğin herkes bir Sam Lantinga kadar grafik programlama bilip SDL kütüphanesini yazamaz. D'nin sunduğu bu olanakla C kütüphaneleri için ilmek yazıp istediğiniz gibi kullanabiliyorsunuz.

Ayrıca C standart kütüphanesini D içinden kullanabiliriz. Örneğin şöyle bir kod geçerlidir:

import std.c.stdlib;
import std.stdio;

void main() 
{
    char[] yazı;
    yazı = "merhaba".dup;
    printf("bir şeyler yazalım = '%.*s'\n", yazı);
}


Alıntı yapılan: Tagli - 30 Ocak 2012, 08:25:35
Ayrıca "extern (C)" ifadesi sanki C kodu çağırıyor gibi. Yanılıyor muyum?

Evet haklısınız  :) Ama burada outb işlevi yerine outp işlevini kullandım.

elektronikhobi

Ben sanki çağırır diye biliyorum ama. Acaba yanlış mı biliyorum  ???

Bakın bu adreste de SDL kütüphanesi için ki tamamen C ile yazılmıştır. D ilmekleri yazmıştım.

https://github.com/erdemoncel/oyun

elektronikhobi

Alıntı yapılan: gerbay - 31 Ocak 2012, 10:31:41

dmd nin sample larından winsamp ı inceleyin, neden giriş fonksiyonunun;

extern(Windows)
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
{
    int result;
    void exceptionHandler(Throwable e) { throw e; }

    try
    {
        Runtime.initialize(&exceptionHandler);
        result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
        Runtime.terminate(&exceptionHandler);
    }
    catch (Throwable e)
    {
        MessageBoxA(null, e.toString().toStringz, "Error", MB_OK | MB_ICONEXCLAMATION);
        result = 0;
    }

    return result;
}


extern(Windows)  şeklinde tanımlaıyorken pencere oluşturan kısmın fonksiyon adında;
int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)


neden buna ihtiyaç duyulmadığını düşünün..

Çok basit çünkü üstteki WinMain işlevinin bildirimi, alttaki ise tanımı. Kısacası üst taraftaki Win32 kütüphanesine D'nin erişmek için kullandığı bir ilmek iken alttaki işlevin kendisi.

Konuları olduğundan karmaşık mı gösterdiğinizi düşünmeye başladım acaba  :D

elektronikhobi

Evet sizin söylediğiniz her şeyi kontrol ettim. Bir tanesi bir DLL oluşturma örneği. Biraz düzeltince derleniyor.

std.demangle örneği de phobos 1'den mi kalmış?

https://github.com/D-Programming-Language/phobos/blob/phobos-1.x/std/demangle.d

Benim önümde şu an TDPL var. 359. sayfa aynen aktarıyorum:

D modules can interface directly with C and C++ functions. The restriction is that template C++ functions are not allowed because that would require the D compiler to include a full-fledged C++ compiler. Also D's class layout is not compatible with C++ classes that use virtual inheritance.

To call functions defined in C and C++, simply specify the language in the function declaration and make sure to link your module with the appropriate libraries:


extern(C) int foo(char*);
extern(C++) double bar(double);


The declarations cue the D compiler to generate calls with the appropriate stack layout, calling convention, and name encoding (aka name mangling), even though D functions themselves are different in some or all of these aspects.


Aynı ifadeyi Alexandrescu da kullanmış. Yani C ve C++ işlevlerini çağırabilmek için .. diye gidiyor. Bu arada derleyici de sizin bahsettiğiniz bazı işlemleri yapıyormuş.

Ama ben bir kitapta bir şey okumuştum (sanırım C++ in Action dı) İnsan derleyicilere ihtiyacımız yok. Çünkü insanlar hata yapabilir diyordu.  Demek istediğim biz kullanmak istediğimiz C veya C++ işlevlerini çağırmak için böyle bir kod yazmamız gerektiğini biliyorsak, derleyicinin ya da bağlayıcının arka planda yaptığı işlerle neden ilgilenelim ki?

Erdem

#7
Sonunda biraz uğraşarak da olsa C ilintilerini yazdım. Artık uygulamalar platformdan bağımsız olarak çalışıyor  ;)

Ayrıca hem windows hem de linux için kaynak kodunu aynı dosyada topladım.

Windows altında tek yapmanız gereken make -f win32.mak ile kodu derlemek ve uygulama klasöründe oluşan programı çalıştırmak.

https://github.com/erdemoncel/elektronikhobi/

mesaj birleştirme:: 13 Temmuz 2012, 21:21:01

Bir de aradan uzun zaman geçmiş. Ama şimdi bu tartışmayı okuyunca aslında @gerbay hocamla aynı şeyleri söylemeye çalışmışız ama bir yanlış anlaşılma olmuş diye düşünüyorum.

Örneğin ben orada çağırır diye biliyorum ama derken anlatmak istediğim C işlevlerini çağırabilmek için bu ifadeleri ekleriz demek istemiştim. Zaten orada bir işlev çağrısı olmadığı açıkça görülüyor.

Daha sonra @gerbay hoca  işte derleyici C işlevlerini kullanabilmek için arka planda süslemeler (name mangling) yapıyor, ya da program yığıtına belirli bir sırada yerleştirmek için çağrılar yapıyor. Onlardan bahsetmiş.

extern(C) , cdecl çağrı yöntemi için extern(Windows) ise stdcall çağrı yöntemi (calling convention) için kullanılıyor.

Konunun ayrıntılarını merak edenler buradan okuyabilir.