June 04, 2020

Ali hocam ve Erdem hepsi çalıştı. teşekkürler..

Aslında söylenilenlerin farkındayım.. Ali Hocam bu sefer terminal ile etkileşmedi diye D ye kızmamıştım. Zaten Dilin her ortamda çalışma kararlılığını bozacak bir durum olurdu. Garip şekilde Programlama konusunda çok basit konularda anlama zorluğu çekerken bazı konularda gerçekten iyi bir temele sahip olduğumu düşünüyorum. Bunları neden söylüyorum çünkü aşağıdaki konuda Ali hocadan fırça yemeden ortamı yumuşatmak için :-D )

Konu bir şekilde kütüphanelere gelmişken şu ilinti işi hala kafamda tam olarak oturmadı. Çok basit bir konuda büyük bir yanlışın içindeyim ama nedir bilemedim.. Örneğin bir C programı düşünelim.. biri "cece.c" diğeri de "cece.h" olsun. *.h iki fonksiyonun bildirimi olsun, "cece.c" de bu fonksiyonları içeren basit bir programcık olsun örneğin fonksiyon ismi yazC() olsun, diğeri de kareKok() olsun.. Ne diyelim bu yazC() onksiyon ekrana "Selam C kullanan D" yazdırsın ve kareKok() fonksiyonuda C deki sqrt() yi kullanarak 16 sayısının karekökünü alan ve akrana yazdıran bir fonksiyon olsun..

Şimdi başlayalım... D diliyle program yazacağım ve bu fonksiyonuda kullanacağım.. öncelikle bu C programıcığını (belki de kütüphanesini ) bir D dili ilintisini yazmalıyız.. işte bunoktada bana bir ilinti yazarsanız ve D programınds programa ekleyerek paylaşırsanız tam olarak bu işi kavrayacağım ve neyi doğru neyi yanlış anladığımı tam olarak çözeceğim. (http://ddili.org/ders/d/moduller.html#ix_moduller.ilinti burada anlatılmış ancak yukarıda yazdığım gibi daha basit örnek belki daha iyi olacaktır )

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

June 04, 2020

C, C++, ve D (ve benim bilmediğim başka programlar); çalıştıkları ortam hakkında çok az varsayımda bulunurlar: stdin, stdout, stderr. Yani, bu diller klavye ve ekran kavramlarını bile içermezler. Buna neden olarak, bu dillerin buzdolabı gibi her tür cihaz içinde çalışan programlar için kullanılabilmesi gösterilir.

Bu yüzden, terminal etkileşimini ancak kütüphaneler yoluyla sağlarlar. Bir programın ncurses gibi bir kütüphane gerektirmesi bazen bir eksiklik veya güçlük gibi görülse de, aslında programın üstü kapalı olarak "ben terminal gerektiririm" demesi gibi bir şeydir ve bunda kötü bir taraf yoktur.

Aşağıdaki olaya girmeden önce Adam Ruppe'nin çok yaygın kullanılan ve çok yararlı olan modüllerine bakmakta yarar var. Kendim kullanmadım ama örneğin aşağıdaki modül işe yarayabilir:

https://github.com/adamdruppe/arsd/blob/master/terminal.d

Terminal etkileşimi için çok yaygın bir kütüphane, ncurses'tir. Bu forumda da daha önce çok konuştuk.

Hatırlatmak için:

  • D, başlık dosyaları kullanmadığından C kütüphanelerini D'de kullanmak için o kütüphanelerin ilintilerine ihtiyaç var. Bunun için başkalarının sundukları ilinti modülleri de kullanabilir, gereken işlevleri ve tanımları yazarak kendimiz de oluşturabiliriz. (Ben burada kendim yazacağım.)

  • O kütüphane dosyasının D programı ile bağlanması gerekir. Bu, bu program için derleme satırına '-L-lcurses' yazarak sağlanabilir.

Terminal konusunda yanıtlanması gereken çok soru var:

  • Bir tuşa basıldığında o tuş ekrana yazılsın mı? Yazılsa, ekranda karakteri ilerletilen oyun yazamayız çünkü örneğin boşluk tuşuna basıldığında bir şey olacaksa her basışta ekran kayar. Yok eğer o tuş ekrana yazılmayacaksa bu sefer de kullanıcıdan bilgi girmesini istediğimizde yazdığı karakteri göremez.

  • Klavyeden tuş okunduğunda takılıp bekleyelim mi yoksa programa hemen geri dönüp "tuş basılı değil" mi diyelim. Bunların ikisi de farklı programlarda yararlı davranışlardır.

  • vs.

O yüzden, ncurses'in de bir sürü ayar işlevi var.

Ortalıkta çok sayıda ncurses bilgisi var. Bir örnek:

http://www.cs.ukzn.ac.za/~hughm/os/notes/ncurses.html

Ben, bizim forumda arayarak bulduğum bir programı denedim ve ne yazık ki çalışmadığını gördüm:

http://ddili.org/forum/post/222

Orada gösterilen benim_ncurses.d modülünde tek değişiklik gerekiyor. Aşağıdaki değişkenin başına __gshared ekleyin:

__gshared WINDOW * stdscr;

Onun dışında, orada gösterildiği gibi derlendiğinde çalışıyor.

Tabii bir de ncurses'in sisteminizde kurulu olması gerekiyor. Çok kolay:
'
$ sudo apt-get install ncurses-dev
'
Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

June 04, 2020

Ali hocam konuyu tamemen anladım. Tekrar teşekkürler. Aslında ilintinin ne anlama geldiğini ilk okuduğumda da anlamıştım. Zaten her defasında bıkmadan usanmadan yazdığınız şu söz;'D, başlık dosyaları kullanmadığından C kütüphanelerini D'de kullanmak için o kütüphanelerin ilintilerine ihtiyaç var.' anlaşılmayacak türden bir yazı değildi. Belki dili yeni öğrenenler belki sadece benim için anlaşılmayan konu aslında sizin aşağıdaki yazdığınız şu satırlar ile çözülmüş oldu :)

'.....
gcc -c cece.c -o cece_C.o
dmd cece.d cece_C.o -of$@
....'

Özetlersem: ilintinin ne anlama geldiğinden çok söz konusu uygulamadaki C kütüphanesinin de derleme sırasında programa dahil edilmesi konusuymuş. (Belki yine yanlış yazdım eğer C programından *.o ürettiğimize ve bunu D programımızı derlediğimize göre,belkide derleme değil de Bağlama sırasında demeliydim)

  • C kütüphanesini al (C ile C programları derlendiğinde oluşan *.o dosyası D deki extern ifadesiyle yapılan ilinti sayesinde D ile tam olarak konuşabilecek düzeye gelmiş olacak )
  • D ye ekleyeceğin bu C programına, C kütüphanesinde kullanılan bildirimler için bir modül yap (C nin ilintisi) (genelde C programlarında bildirimler *.h başlık dosyalarında olduğu için sadece bunu D için düzenlememiz yeterli olacaktır..)
  • D programını bu oluşan *.o ve D program modülleri ile birlikte derle ve bağla..

Şimdi ne oldu C programını D ile konuşturduk ve anlaştırdık. Başka programlar neden bunu yapamıyor çünkü her ne kadar *.o derlenmiş dosyası oluşsa ve bunu atıyorum Z dili derleyicisiyle derlesek/bağlasak bile C komutlarını tanımayacağından bunu yapamıyor ama D dili 'extern' olanağı sayesinden bu sorunu ortadan kaldırıyor.. (Aslında başka dosyaların *.o dosyalarını bağlamak için D dilinin yanlız olmadığını biliyorum ama konumuz değil)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

June 04, 2020

Bir konuya daha değinmeden geçemeyeceğim Ali hocam. Kendinize biraz haksızlık ettiğiniz için cevap vereceğim :-)

Alıntı (acehreli):

>

Alıntı (cos00kun):

>

Çok basit bir konuda büyük bir yanlışın içindeyim ama nedir bilemedim.

Ben bu güne kadar doğru sözcükleri seçmemiş olmalıyım. .h dosyasındaki ....
....

Ali hocam sorun sizde değil bizde :-p
Siz Kitabınızı Türkiyede bile konuşulamayacak kadar güzel Türkçe ifadelerle zaten yazdınız.

Bir yerlerde okumuştum aslında Yabancı Dil öğrenmenin ilk kuralının kendi dilinizi ve kurallarını iyi biliyor olmanız gerekliliği ile ilgili bir yazıydı sanırım. Ben bu konuda pek başarılı biri değilim ama bu çok doğru bir tespit. Bence bu sadece yabancı dil değil programlama içinde geçerli. Aslında yazılanların anlamlarını gerçekten iyi okuyup anlarsak birçok konu kendiliğinden çözülüyor. Kendi adıma konuşayım belki hepsi değil ama bugüne kadar sorduğum soruların %60-70 arasındakileri gerçekten iyi anlayarak okusaydım yapabilirmişim..

Programlamadan daha çok muhabbet ortamı yarattım kusura bakmayın ama ıssız adada insanın canı sıkılıyor :-p
görüşmek üzere..

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

June 04, 2020

Alıntı (cos00kun):

>

Çok basit bir konuda büyük bir yanlışın içindeyim ama nedir bilemedim.

Ben bu güne kadar doğru sözcükleri seçmemiş olmalıyım. .h dosyasındaki bildirimleri anlıyorsan ilintinin ne olduğunu da aslında biliyorsun: C bildirimlerinin D dosyasına yazılmış hali. (Çoğu durumda kopyalamak kadar basit.)

// cece.h --------------------

void yazC(const char * s);
double kareKok(double i);
// cece.c --------------------

#include "cece.h"
#include <stdio.h>
#include <math.h>

void yazC(const char * s) {
 printf("yazC ile: %s\n", s);
}

double kareKok(double i) {
 return sqrt(i);
}
// cece.d --------------------

module cece;

import std.stdio;
import std.string;

// İşte bunlar ilintiler:
extern(C) void yazC(const char * s);
extern(C) double kareKok(double i);

void main(string[] args) {
 writeln("kök(42): ", kareKok(42));

 // D hazır değerlerinin sonunda '\0' vardır. O yüzden C işlevlerine
 // doğrudan gönderebiliriz:
 yazC("merhaba");

 // Hazır değer olmayan D dizgilerinin sonunda normalde '\0'
 // bulunmaz. O yüzden C işlevlerine göndermeden önce sonuna '\0'
 // karakterini ekleyen toStringz'yi çağırmamız gerekir:
 auto mesaj = format!"Komut satırı şuydu: %-(%s %)"(args);
 yazC(mesaj.toStringz);
}

Programı oluşturan (ve çalıştıran) bir Makefile:
'
cece_deneme: cece.h cece.c cece.d Makefile
gcc -c cece.c -o cece_C.o
dmd cece.d cece_C.o -of$@
./$@
'
İlintiler cece.d dosyasının içinde. Tabii başka bir D dosyasına yazılım import da edilebilirdi. extern(C) önemli, C makrolarını D'ye taşırken bazı kararlar vermek gerekiyor, struct tanımlarının sonundaki noktalı virgüller atılıyor, vs. biraz emek gerekebiliyor ama sonuçta ilinti, C dosyasında bildirimin D tarafında yapılmasıdır.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

June 05, 2020

Alıntı (acehreli):

>

Alıntı (cos00kun):

>

C komutlarını tanımayacağından bunu yapamıyor

Alıntı:

>

Derlenmiş .o dosyasının dille ilgisi kalmamıştır; doğrudan makine kodlarından oluşur. Zaten o yüzden derlenmiş kodları kaynak dillerinden bağımsız olarak bağlayabiliyoruz.
..
Ali

Ali hocam haklısınız.. Aslında anlattıklarınızı zaten anlamıştım ama yukarıda bu konuyla ilgili yazdıklarıma bakınca anladığım konuyu tam olarak ifade edemediğimi farkettim. Yinede daha fazla bilgi kazanmış oldum teşekkürler :) En azından bu konu tamamdır (Yeni problemler çıkana kadar :) )

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

June 05, 2020

Alıntı (cos00kun):

>

C programından *.o ürettiğimize ve bunu D programımızı derlediğimize göre,belkide derleme değil de Bağlama sırasında demeliydim

Evet, bağlama zamanında kullanılacak ama derleme satırına yazıldığı için biraz karışıklık oluyor. :)

Alıntı:

>

bu oluşan *.o ve D program modülleri ile birlikte derle ve bağla..

Doğru ama .o yerine .so (dinamik kütüphane) veya .a (statik kütüphane) de olabilirdi tabii. Ben basitçe .o oluşturdum. Zaten kendi programımda .c dosyaları olsaydı yine .o olarak kullanırdım. Amacım kütüphane sunmak olsaydı .so veya .a'yı o zaman düşünürdüm.

Alıntı:

>

C komutlarını tanımayacağından bunu yapamıyor

Derlenmiş .o dosyasının dille ilgisi kalmamıştır; doğrudan makine kodlarından oluşur. Zaten o yüzden derlenmiş kodları kaynak dillerinden bağımsız olarak bağlayabiliyoruz.

D'deki extern(C), C++'taki extern "C", vs. olanaklarının bu konuda yaptıkları en önemli şey, derlenen koddaki işlev çağrılarını C'nin işlev isimlendirmesine uygun olarak yapmalarıdır. Yani, D'de extern(C) olan bildirilmiş olan bir işlev, C derleyicileri işlevleri nasıl adlandırıyorsa o ad ile çağrılır. (extern(C) parametrelerin program yığıtında hangi sırada geçirildiklerini de belirler.)

Denemek için şu programı kullanalım:

module deneme;

void foo(int i);

void main() {
 foo(42);
}

Derlediğimizde, bağlayıcı bize '_D6deneme3fooFiZv' isminin bulunamadığını söyler:
'
deneme.d:(.text._Dmain[_Dmain]+0xa): undefined reference to `_D6deneme3fooFiZv'
'
Bunun nedeni, foo'nun varsayılan extern(D) olarak bildirilmiş olmasıdır. O garip ismin içinde, modül isminin yanında işlevin hangi türlerden parametre aldığı gibi bilgiler de gizlidir. (Denemek için int'i başka türlerle değiştirin ve ismin nasıl değiştiğini görün.)

Aynı programı foo'yu extern(C) olarak bildirerek derleyince hata mesajında gördüğümüz isim çok daha basittir:
'
deneme.d:(.text._Dmain[_Dmain]+0xa): undefined reference to `foo'
'
Bunun nedeni, C dilinde isim alanı, işlev yükleme, vs. gibi olanakları bulunmamasıdır.

Özetle, extern(C)'nin buradaki amacı, programda kullandığımız isimlerin kütüphanenin sundukları uymasını sağlamaktır. (Dediğim gibi, parametre sırası da önemlidir ama o farklılık çalışma zamanı hatası olarak görülür.)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

1 2
Next ›   Last »