Programlamadili.Net Yeni Nesil Programlama Portali
Makale Ara: 
Kullanıcı Adı : Şifre :
  • Makale Kategorileri
Anasayfa
ACPI [0]
Action Script [5]
Ajax [7]
ASP [12]
ASP.NET [23]
Assembly [3]
Bash [1]
C [4]
C# [9]
C++ [10]
Cobol [1]
Delphi [31]
Flash [5]
Html [9]
JAVA [36]
Java Script [12]
JSF [2]
Jsp [5]
Lua [1]
Matlab [2]
MySQL [30]
Oracle [1]
Pascal [31]
Perl [4]
Photoshop [2]
PHP [150]
Python [8]
REXX [6]
Ruby [1]
SEO [5]
Visual Basic [37]
  • Gorsel Ders Kategorileri
Asp [25]
Asp.Net [5]
Csharp [33]
Delphi [3]
Fireworks [4]
Flash [10]
Java Script [0]
Photoshop [0]
PHP [54]
Vb.Net [9]
Visual Basic [4]
  • Dil
English
Deutsch
deutsch
  • Reklam Alani
C++ / Windows API ve C- (3)
Windows API ve C- (3)
Yazar: by_Coder
Eklenme: 25/01/08    Okunma: 314    
 
 

DLL Dosyaları

İki ay süren uzun bir yaz tatili arasından sonra yine birlikteyiz sevgili C ve WinAPI meraklıları. Biliyorum, bir önceki makalede bu bölümde kontrollerden bahsedeceğiz demiştik ama planlar değişti :). İki ay boyunca "ne yazsam, ne yazsam" diye elektronik cihazlardan uzak günler geçiren bendeniz, en sonunda okuyucuların en çok merak ettiğini düşündüğüm, Windows API sisteminin çalışmasında hayati bir rol oynayan ve düzgün kullanıldığı zaman çok işe yarayan, hatta ve hatta hayatınızı kolaylaştırabilecek çok özel bir dosya türüne değineceğim: DLL.


Dinamizm ve Windows - Ne İşe Yarar?

Başlığa bakıp "ıhhh!" dediğinizi duyar gibiyim, neyse ki burada bahsedeceğimiz dinamizim hız ile ilgili değil, daha çok modern programlama dillerinde gördüğümüz dinamik ve durağan (statik) veri tipleriyle ilgili.


Öncelikle terminolojinin karanlık yüzünün bir parçasını daha aydınlatalım; DLL kısaltması, Dynamic Link Library anlamına geliyor. Artık bunu da açıkladığımıza göre, ne işe yaradığını da anlatabiliriz. DLL dosyaları, özel bir şekilde bir araya getirilmiş fonksiyonlar ve veriden oluşan bir bütündür, yani yapı olarak EXE dosyalarından o kadar da farklı değildir. Ama işlev olarak bambaşka işlere yarar, fonksiyonları "ihraç" etmeye (export). Windows altında çalışan herhangi bir uygulama (DLL, EXE) adını ve parametre dizimini bildiği sürece DLL dosyaları içinden fonksiyon çağırabilir. Bütün WinAPI çağrıları, DLL dosyaları üzerinden yapılır. Hiç bir programa programcı gözüyle bakıp "vay canına, adam ne fonksiyonlar yazmıştır bunun için!" dediğiniz oldu mu? DLL dosyaları sayesinde insana "vay" dedirten o fonksiyonları siz de kullanabilirsiniz (örnek mi? MP3 kodlama, JPEG oluşturma, üç boyutlu nesneler çizme...aklınıza ne gelirse).


Böylece ne işe yaradıklarını öğrenmiş olduk. Programcının hayal gücü geniştir, nerelerde kullanılabileceği ile ilgili bir sürü fikriniz vardır, ama ben birkaç örnek vereceğim.



Eğer aynı fonksiyonu kullanacak iki (veya daha fazla) programınız varsa, aynı kodu tekrar yazmak zorunda değilsiniz, bir DLL dosyası sorunu çözecektir. Böylece fonksiyonlar programlarda ayrı ayrı derlenip gereksiz yer kaplamayacaktır (WinAPI çağrılarını kullanan her program için tekrar yüzlerce satır yazılacağını düşünün...)
Diyelim ki anlamadığınız bir dilde veya anlayamayacağınız zorlukta ama çok ihtiyacınız olan bir kodla karşılaştınız. Eğer bu kod bir DLL dosyasından ihraç edilmişse rahatlıkla çağırabilir ve kullanabilirsiniz.
Programı kullanıcılarınıza dağıttıktan sonra fonksiyonlarınızın birinde bir hata keşfettiniz ve düzelttiniz. Şimdi programı bir daha dağıtmanız gerekecek, kolay gelsin :). Tabii eğer fonksiyonunuz bir DLL içinde bulunsaydı megabaytlarca veri yerine küçük bir DLL dosyası gönderecektiniz.

Bunun gibi örnekleri çoğaltabiliriz. Anlayacağınız, DLL dosyaları bize modüler mutfakların veya kasası açılmayan bir bilgisayarın çevre birimlerinin sunduğu kolaylıkları sunuyor (klavyeniz bozulduğunda anakartı da değiştirmek zorunda kalacağınızı düşünün).


 


Kodu Bağlamak - Nasıl Çalışır?

Programınıza bir fonksiyon yazıp derlediğiniz ve bağladığınız zaman fonksiyonun içerdiği kod makine koduna çevrilir ve kodun bulunuğu ünitenin içindeki yerini alır. Fonksiyonun adı artık kod içindeki adresidir, programınızın içinden bu fonksiyon çağrılacağı zaman fonksiyona geçilecek parametreler "stack" denilen veri alanına alınır ve işlemci xxx adresindeki koda atlar (bu fonksiyonunuzun adresidir). Fonksiyon kodunun sonunda döndürülecek değer varsa kaydedilir (meraklısına, EAX adlı register içine) ve kod kaldığı yerden devam eder. Kod değiştirilip program tekrar derlenene ve bağlanana kadar bu adresler değişmez, yani durağandırlar. Bu tip bağlama işlemi durağan bağlama (static linking) olarak adlandırılır.


Ama eğer program bir DLL dosyasından çağrı yapıyorsa durum farklıdır, çünkü DLL içindeki fonksiyonun tam adresini program saptayamaz. Bu sorun iki şekilde çözülür:



Yükleme Zamanı Dinamik Bağlamada (Load-Time Dynamic Linking) DLL ile birlikte gelen .lib dosyasını (import library, "ithal kütüphanesi" diye çevriliyor, ne hoş..) EXE projenize dahil edersiniz. Bu dosya DLL içinde bulunan fonksiyonların (ve adreslerinin) bir listesini barındırır. Programı EXE yaptığınız zaman bağlayıcı EXE dosyanın bir bölümüne bu adresleri yazar. Bu EXE dosyasını çalıştırdığınız zaman Windows gerekli DLL dosyalarını yükler ve programa istediği fonksiyonların adreslerini bildirir. Bu şekilde dinamik bağlama yaptığınız zaman Dependecy Walker tarzı bir program kullanılarak EXE'nin hangi DLL dosyalarından hangi fonksiyonları kullandığı anlaşılabilir.
Çalışma Zamanı Dinamik Bağlamada (Run-Time Dynamic Linking) .lib dosyasına ihtiyaç yoktur. LoadLibrary API fonksiyonunu çağırarak DLL dosyasını yükler ve GetProcAddress API fonksiyonunu kullanarak istediğiniz fonksiyonun adresini alır ve çağırırsınız. Bu bağlama şeklinde programınızın hangi DLL'leri kullandığını anlamak daha zordur.

Tıpkı EXE dosyalarında olduğu gibi aslında DLL dosyaları içinde de kodun çalışmaya başlayacağı bir giriş noktası (entry point) fonksiyonu bulunur ama bu bir zorunluluk değil. Eğer DLL hafızaya yüklenir yüklenmez bir şeyler yapmak istiyorsanız, entry point fonksiyonunu yazmanız gerekiyor:


BOOL DllMain(HINSTANCE hInst,DWORD fdwReason,LPVOID lpvReserved);

hInstance, WinMain fonksiyonundaki benzeriyle aynı işlevde, fdwReason parametresi ise DLL yükleniyor, başka bir program tarafından çağrıldı, hafızadan siliniyor gibi durum mesajlarını alıyor. Sonuncu parametre ise fdwReason'un iki durumuyla bağlantılı. Ben bu makalede DllMain kullanmayacağım.


 


Under Construction - Nasıl Yapılır?

Şimdi de DLL dosyalarının yapım ve kullanımı ile ilgili diğer detaylara değinelim. Öncelikle, uzantı ve yapıları EXE dosyalarından farklı olduğu için programlama aşamasında bazı farklılıklar var. Hangi geliştirme ortamını kullanıyorsanız projenizi yaratırken DLL olarak yaratmanız gerekiyor. Kodu yazarken dikkat etmeniz gereken birkaç nokta da var; mesela ihraç edeceğiniz fonksiyon isimlerini, parametreleri ve dönen değerlerin tiplerini dikkatli seçmelisiniz. Bir de calling convention meselesi var ki evlere şenlik. Eğer yazdığınız DLL dosyasını VB'den çağırmak istiyorsanız kesinlikle fonksiyonlarınızı kesinlikle __stdcall biçemine uygun yazmanızı tavsiye ediyorum. Fonksiyonu bu convention'a uyumlu yapmak için döndürülen değer adından sonra __stdcall ekleyin:


int __stdcall Topla(int a,int b);

İhraç etmek istediğiniz fonksiyonları yazdıktan sonra, bir de bağlayıcıya hangilerini ihraç etmek istediğinizi, hangilerini istemediğinizi anlatmanız gerekiyor. Bunu projenize bir .def dosyası ekleyerek yapabilirsiniz (bir de __declspec(dllexport) metodu var çok kullanılmayan). Bu dosya, .def uzantılı normal bir text dosyasıdır. İçine EXPORTS kelimesinden sonra her bir satıra ihraç etmek istediğiniz fonksiyon adlarını yazarsınız:


EXPORTS
Topla

Son olarak, bir uygulamanın bir DLL dosyasını kullanabilmesi için Windows o DLL dosyasını aşağıdaki sırayla belirtilen yerleri arar:



Programın kendi dizini
Geçerli dizin
Windows sistem klasörü
Windows klasörü
PATH ortam değişkeninde bildirilen klasörler

Bu kadar şeyi ard ard görmek kafa karışıtırıcı olabilir, hele hepsini hatırlamak daha da zor, o yüzden bir örnek faydalı olacaktır.


 


DLL Yazmak, Derlemek ve Bağlamak

Projemizi yarattık, bir adet main.cpp dosyası ekledik ve içine aşağıdaki kodu yazdık diyelim:


#include <windows.h>


int __stdcall Topla(int a,int b)
{
return a+b;
};

Görebileceğiniz gibi çok ahım şahım bir kod örneği değil yukarıdaki, ama DLL gibi karmaşık bir konuda basit örneklerle başlamak en iyisi. Bu adımdan sonra (yine VC++ kullandığınızı varsayıyorum) projemize projeyle aynı adlı bir .def dosyası ekliyor ve içine şunları yazıyoruz:


EXPORTS
Topla

Şimdi gönül rahatlığıyla DLL dosyamızı derleyebiliriz. Kod zaten basit, hatasız bir şekilde derlenecektir. DLL dosyamız hazır, şimdi bir de onu kullanmamız lazım.


 


DLL İçinden Fonksiyon Çağırmak

Önceki bölümlerde DLL çağırmanın iki yolu olduğndan bahsetmiştik, bu örnekte çalışma zamanı dinamik bağlama kullanarak DLL içinden fonksiyonumuzu çağıracağız. Bu iş için kullancağımız üç temel API fonksiyonu var: HINSTANCE LoadLibrary(LPCTSTR lpLibFileName) - dosya adı verilen DLL'i hafızaya yükler ve referansını döndürür FARPROC GetProcAddress(HMODULE hModule,LPCSTR lpProcName) - hModule içinde referansı verilen DLL dosyasından pProcName parametresinde adı verilen fonksiyonun adresini döndürür BOOL FreeLibrary(HMODULE hLibModule) - referansı verilen DLL dosyasını uygulamadan serbest bırakır ve gerekirse hafızadan kaldırır Bu API fonksiyonlarının kullanımı oldukça basit, asıl sorun fonksiyon adresini aldıktan sonra onu parametre geçilip çağrılabilecek hale getirmek. Bunun için yazımı karışık bir typedef kullanmamız gerekiyor. Şablon şu şekilde:


typedef dönentip (*fonksiyonadı)(parametre1tip,parametre2tip...);

Örnek olarak kendi fonksiyonumuzun tip tanımı:


typedef int (*dllfonk)(int,int);

Şimdi kendimize yeni bir EXE projesi yapıp aşağıdaki kodları yazalım:


#include <windows.h>
#include <stdio.h>


typedef int (*dllfonk)(int,int); //fonksiyon tanımı

int main(void)
{
HMODULE hDll; //dll referansını tutacak
dllfonk AlFonk; //dll içinden çekilen fonksiyon adresini işe
yarar hale getirecek
hDll=(HMODULE)LoadLibrary("DllDeneme.dll");
if(!hDll)
{
MessageBox(NULL,"DLL yüklenemedi","Hata",MB_OK);
return 0;
};
AlFonk=(dllfonk)GetProcAddress(hDll,"Topla"); //fonksiyon adresini al
if(!AlFonk)
{
MessageBox(NULL,"Fonksiyon bulunamadı","Hata",MB_OK);
FreeLibrary(hDll); //dll'i serbest bırak
return 0;
};
//fonksiyon hazr, artık çağırabiliriz
printf("15855+98888=%d
",AlFonk(15855,98888));
FreeLibrary(hDll); //dll'i serbest bırak
return 0;
};

Bu kodu da yazıp derledikten sonra DLL ve EXE dosyalarını aynı klasöre koyup EXE'yi çalıştırarak DLL mucizesine kendi gözlerinizle tanık olabilirsiniz :). Böylece bu makalenin de sonuna geldik. DLL konusu fazlaca kafa karıştırır nitelikte olduğu için örnek kodları buradan indirip incelemek isteyebilirsiniz. İsterseniz DLL dosyasını sistem klasörü veya windows klasörü içine atıp oradan da çalıştırabilirsiniz.




Taglar: C Programlama ile Dongulere Ornek Vermek Donusturme C Programlama Ile 3d Ekran Koruyusu C Programlama Ile Guzel bir Hesap Makinasi KodBank Cplus programlamada Dizi fonksiyonlari Sayinin negatif yada pozitif oldugunu bulma Windows API ve C - 1 Windows API ve C - 2 Windows API ve C - 4 Windows API ve C - 5 Windows API ve C- 3

Isminiz:
E-mail adresiniz:
Güvenlik Kodu:
  
 

 

Istatistikler ,
Sitemizde su anda 31 kategori, 453 makale , 147 görsel ders ve 128 Ziyaretci bulunmaktadir...
Toplam üye sayimiz : 951

Web Stats Ferdi Tayfur | Memur Muzaffer | Bedava Mp3 indirin | Visual Basic | Rss| Fnex.Net| Forum Dünyasi
Pagerank

Copyright © 2007 Programlamadili.net - Programlama & Tasarim: Recep Ikiz & Ferdi Küçük

| Site Haritasi |

"Ne Aradığını Bilmeyen Bulduğunun Farkına Varamaz "
ACPI Programlama dili, Action Script Programlama dili, Ajax Programlama dili, ASP Programlama dili, ASP.NET Programlama dili, Assembly Programlama dili, Bash Programlama dili, C Programlama dili, C# Programlama dili, C++ Programlama dili, Cobol Programlama dili, Delphi Programlama dili, Flash Programlama dili, Html Programlama dili, JAVA Programlama dili, Java Script Programlama dili, JSF Programlama dili, Jsp Programlama dili, Lua Programlama dili, Matlab Programlama dili, MySQL Programlama dili, Oracle Programlama dili, Pascal Programlama dili, Perl Programlama dili, Photoshop Programlama dili, PHP Programlama dili, Python Programlama dili, REXX Programlama dili, Ruby Programlama dili, SEO Programlama dili, Visual Basic Programlama dili,
Reklam alanı