> Delphi > C / C++ ‘dan Delphi’ye Kod Çevirme Klavuzu (1)

C / C++ ‘dan Delphi’ye Kod Çevirme Klavuzu (1)

Özellikle işe yarar bir kütüphane bulduğunuz zaman eğer yoksa hemen Delphi sürümlerini araştırırız. Çoğu zaman “Delphi port” ismiyle, kütüphanelerin Delphi versiyonlarına erişebiliriz. Eğer Delphi versiyonlarını bulamazsak, iş başa düşmüş demektir. Kütüphaneler bir çok dilde olabilirler. Fakat genel manada en çok C++ veya C kodlarının adaptasyonu ve çevrilmesi programcıları zorlayabilmektedir.

Bu yazımızda C / C++ ve Delphi gramer bilgisi vermek yerine, daha çok C / C++ kodlarını en doğru şekilde Delphi’ye nasıl adapte edebileceğimizi göreceğiz. Yapacağımız işlem sadece bire bir kod çevirisi olmayacak. Yeri geldiğinde hiç bir kod çevirmeden sadece orjinal kütüphaneyi Delphi programımızın içine gömebileceğiz.

Eğer siz de, ister derlenmiş olsun, ister açık kaynak kodlu olsun, bir C / C++ kütüphanesini Delphi’ye nasıl çevirebileceğimizi merak ediyorsanız buyurun beraber yazımıza giriş yapalım.

Giriş

C / C++ ‘dan Delphi’ye kod çevirme derken ilk akla gelen, binlerce satırlık C kodlarını teker teker uğraşıp Delphi olarak yazmak gelecektir. Halbuki bu en son tercihimiz olması gerekmektedir. İlerleyen bölümlerde de göreceğimiz gibi, Delphi derleyicisinin hünerli parmakları bizi bir çok dertten kurtarmaktadır. Yine de bütün kodları baştan çevirmek gibi bir derdin altına girmek isterseniz bu makale size bir başlangıç noktası olacaktır.

Hemen kodlara dalmak gerçekten gerekli mi? Kesinlikle gerekli değil. Çünkü bizim uğraştığımız şey, önceden birileri tarafından yapılıp internet üzerinde dağıtılıyor olabilir. Bu yüzden ilk yapacağımız işlem bir “Delphi port” bulmamız gerekmetedir.

Mesela şuanda en hızlı ve en stabil xml kütüphanesi kabul edilen libxml2 kütüphanesini kullanmak istediğimizde, hemen kodları çevirmeye kalkmak yerine bir Delphi port bulmamız en akıllıca işlem olacaktır. Ki bu kütüphanenin başlık dosyaları zaten sourceforge üzerinde dağıtılmaktadır.

Bu makalede, C objelerinin kullanımı, C veri tiplerinin Delphi’deki karşılıkları, C başlık (header .h) dosyalarının Delphi’ye çevrilmesi gibi bir çok konu bulacaksınız. Bu bilgiler ile istediğiniz bir C kütüphanesini korkmadan Delphi’ye adapte edebilirsiniz.

Bu makalede çok fazla C / C++ bilgisi gerekli mi? Gerekli olsa bu makaleye ihtiyaç duymazdınız. Fakat çok az da olsa C / C++ gramerine aşinalığınız olmak zorunda. En basit olarak bir bir fonksiyon nasıl tanımlanır, bir değişken nasıl tanımlanır, bir pointer nasıl atanır, bunları bilmeniz gerekmektedir.

Fonksiyon Çağırım Mekanizmaları

Bir çinli ile anlaşabilmek için bir tercüman tutmanız gerekti. Fakat çok aramanıza rağmen çinli bir tercüman bulamadınız. Bunun yerine bir birine benziyor diye kalkıp, japonca bir tercüman tuttunuz. Çinli olan birisi ile ne kadar anlaşabilirsiniz. Her ne kadar bize “benzer” gibi gözükse de iki dil bir birinden farklı dildir. Bu örneği şimdi göreceğimiz konuya hazırlamak için verdim. Bu misalden hakikate şu şekilde geçebiliriz. Derlenmiş olan her bir kütüphanedeki fonksiyonlar belli bir dili konuşmaktadırlar. Bu konuştukları diller görünüşte bir birlerine benzeseler de, ayrıntıda bir birlerinden farklıdırlar. Bu konuşulan dillere fonksiyon mekanizmaları ya da ingilizce terim olarak “calling conventions” denilmektedir. Eğer kullanacağınız fonksiyon farklı bir dili kullanıyor ve siz de fonksiyonu farklı bir dil ile çağırıyorsanız muhtemel hatalar ile karşılaşacaksınız. Bu yüzden ilk öğreneceğimiz konu bu olmalıdır.

Direk olarak çağırım mekanizmalarının delphi karşılıklarını vermek yerine az da olsa bir kaç özelliklerinden bahsetmek istiyorum. Çünkü hangi çağırımı nerede ne için kullanacağımızı bilmemiz şarttır.

Şu an literatürde en çok kullanılan 4 çeşit fonksiyon çağırım mekanizması vardır. Bunların ne olduğunu ayrıntısı ile anlatan buradaki makalemize göz atabilirsiniz. Hatta okumadı iseniz bir göz gezdirmenizi şiddetle tavsiye ediyorum. Biz burada bu mekanizmaların çalışma şekillerinden çok işimize yarayan kısmını anlatmaya çalışacağız. Ama linkini verdiğim makalede bunların çalışma şekillerini ayrıntılı bir şekilde bulabilirsiniz.

Birinci olarak göreceğimiz çağırım mekanizması register çağırımıdır. Delphi varsayalın olarak bütün fonksiyon ve metodlarda bu çağırımı kullanmaktadır. Normalde Dehlpi’de “register” ayrılmış kelimesini fonksiyon ya da metodun sonuna eklemekle, fonksiyon ya da metodu bu çağırım için ayarlamış oluruz. Fakat varsayılan olarak kullanıldığı için bunu yazmanıza gerek yoktur:

Fonksiyon çağırım mekanizmaları ile ilgili yazıyı okuduysanız en verimli ve performanslı çağırımın bu olduğunu biliyorsunuzdur. Bu mekanizma ilk olarak Borland tarafından geliştirilip C++ Builder ve Delphi derleyicilerinde kullanıldı. Şu anda bildiğim bütün C / C++ derleyicileri bu çağırımı desteklemektedir. C / C++ derleyicilerinde bu çağırım __fastcall olarak isimlendirilmektedir.

Her ne kadar en hızlı çağırım __fastcall yani register olsa da ve çoğu derleyici tarafından desteklense de, belki de alışkanlıklardan dolayı, C / C++’da pek kullanılmamaktadır. Genelde Linux ve Windows’da ileride gelecek olan başka çağırımlar kullanılmaktadır.

__fastcall yani register çağırımları, Microsoft’uın derleyicilerinde __msfastcall olarak başka bir biçimi de almıştır. Fakat şu anda Delphi bu çağırımı desteklememektedir. Umarım ilerideki Delphi derleyicilerinde bunu görebiliriz. Fakat bu çağırım __fastcall kadar bile yaygın ve fazla kullanılmadığı için şu anda anlattığımız çevirim işlemi için çok da önemli değil. Hatta, eğer bir kütüphane bir çok dili desteklemek gibi bir gayesi varsa __fastcall çağırımını da desteklememektedir.

Kısacası bu çağırımı delphi’ye aktarmak için hiç bir şey yapmamız gerekmiyor. Çünkü delphi bunu varsayılan olarak kullanıyor. Mesela aşağıdaki C fonksiyonunu delphi’ye çevirelim:

İkinci çağırım mekanizmamız __pascal yada delphi’de pascal çağırımıdır. Ki bu çağırım Win 3.1 zamanından kalma eski bir çağırımdır. Bu yüzden eğer karşılaşırsanız yapmanız gereken __pascal yerine pascal yazmalısınız.

Üçüncü çağırım mekanizmamız __stdcall ya da delphi’de stdcall çağırımıdır. Bu çağırım, Windows işletim sisteminin varsayılan çağırım mekanizmasıdır. Eğer windows’a ait bir DLL’i kullanacaksak, bilinki %99 stdcall olarak tanımlanmıştır. __stdacall çağırımı derleyicilerde çeşitli takma adlar ile kullanılmaktadır. Genelde “WINAPI” kelimesi __stdcall için kullanılmaktadır. Mesela aşağıdaki Windows API’sinden bulunan fonksiyonu şöyle çevireceğiz:

Yardım dosyalarında bu fonksiyonun başında WINAPI ya da __stdcall ifadesini görmesek de, biliyoruz ki bu bir Windows fonksiyonudur. Öyleyse bu fonksiyon stdcall çağırımıdır. Bu çıkarım ile hem delphi hem de C kodunda bu çağırımı belli ettim.

Dördüncü ve son çağırımımız ise __cdecl ya da delphi’de cdecl çağırımıdır. Bu çağırım C / C++ derleyicilerinin varsayılan çağırımıdır. Eğer C dosyalarında hernangi bir çağırım belirtilmemiş ise, bu fonksiyon cdecl olarak çağırılacaktır. Yani aşağıdaki fonksiyonlar aynı şeyi ifade edip her iksinin de çevirimi aşağıda gösterilmektedir.

İleride makroları göreceğiz. Aşağıdaki makro tanımlamaları da geçerlidir ve kullanılmaktadır.

__stdcall = _stdcal = CALLBACK = WINAPI = APIENTRY = PASCAL = APIPRIVATE

__cdecl = _cdecl = WINAPIV

__fastcall = _fastcall

Yukarıda eşitliklik ile ifade edilenleri birbirlerinin aynısı olarak kabul edebilirsiniz.

DLL Kullanımı ve Çağırımlar

Normalde bir DLL’den bir fonksiyonu kullanmak için fonksiyonu nasıl tanımlayacağımızı bir hatırlayalım:

Kendi DLL’imizi kullandığımızda fonksiyonu nasıl tanımlayacağımızı biliyoruz. Peki DLL’i biz yazmamış isek ne yapacağız?

Bu durumda, eğer herkes tarafından kullanılabilir bir DLL dosyası ise, DLL sağlayan firma, ekip, yazılımcı, vs. DLL dosyası ile beraber bir “header” dosyası sağlayacaktır.

Delphi’de, bildiğiniz gibi, unit iki bloktan oluşur. Birinci blok yani interface bloğu, unit tarafından “unit dışında” kullanılacak olan sınıf, değişken, fonksiyon, vs. ‘den oluşur. İkinci blok yani implementation bloğu ise, interface bloğunda tanımlanmış olan fonksiyon ve sınıfların esas kodlarından oluşur. Yani esas çalıştırılan kodlar implementation kısmında bulunur. Ayrıca implementation’da tanımlı herhangi bir değişken, fonksiyon, vs. eğer interface’de tanımlı değilse diğer unitlerde görünmezler ve kullanılamazlar.

C / C++ dosyaları da Delphi’nin unit dosya mantığının aynısıdır. Fakat Delphi’nin aksine C / C++ dosyaları tek parça halinde değil iki parça halinde tutulurlar. Delphi’de interface olarak ifade ettiğimiz blok C ‘de “header” olarak ifade edilir ve “.h” uzantısına sahiptir. Nadir de olsa C++’da header dosyaları “.hpp” uzantısı alabilirler. Delphi’de implementation olarak ifade edilen esas çalışan kodlar ise C’de “.c” ve C++’da ise “.cpp” uzantısı ile ifade edilen dosyalardadır.

Header dosyaları, şart olmasa da, genelde kütüphanenin “include” adlı klasöründe barındırılmaktadır. Kullanacağınız DLL’in header dosyası da bu veya bunun benzeri bir klasörde bulunacaktır. Header dosyası olmadan Delphi çevirimi yapmamız çok zor olacaktır. Hatta üst düzey assembler bilginiz olması gerekebilir. Bu yüzden DLL ile beraber en az bir adet header dosyasına sahip olduğunuzu varsayıyorum.

Bu başlık altında esas olarak anlatmak istediğim mevzuya şimdi geliyoruz.

DLL’e ait header dosyasına baktığımızda fonksiyonların hangi çağırım mekanizmalarını kullandıklarını görebiliyor ve anlayabiliyoruz. Fakat derlenmiş olan DLL dosyalarında bu çağırım mekanizmalarını belirten hernhangi bir işaret var mı?

Bunun için yardımcı bir araca ihtiyaç duyacağız. Aslında TDump isimli ve delphi ile beraber gelen bir konsol uygulaması bulunmakta. Ancak konsol uygulaması yerine göresel bir aracı tercih ederim. Ama illaki tdump kullanmak isteyen olursa “-b” parametresi ile beraber kullanabilirsiniz. Her neyse, ihtiyacımız olan program “Dependency Walker” . Bu program ile DLL’de bulunan tüm fonksiyonları isimleri ile beraber görebiliriz.

Peki header dosyasında fonksiyonlar ayrıntılı bir şekilde olmasına rağmen neden ekstra bir araca ihtiyaç duyuyoruz. Aslında ekstra bir programa ihtiyacımız yok. Header dosyaları fazlasıyla yeterlidir. Fakat bazen DLL’ler varsayılan ayarlarla derlenmemektedir. Bu da bize sorun çıkarabilmektedir.

DLL’ler derlenirken fonksiyon isimleri çeşitli ekler alırlar. Bu ekler, fonksiyonun hangi çağırımı kullandığını belirler. Ama bazen bu varsayılan isimlendirmenin dışına çıkan kütüphane yazılımcıları, bütün ekleri kaldırabiliyorlar. Mesela cdecl fonksiyonları önlerinde “_” işaretini barındırırlar. Veya stdcall fonksiyonları fonksiyon isiminden sonra “@” işareti ve parametrelerin boyutlarını içeren bir dizi ekten ibarettirler. Dependency Walker gibi programlar, bize fonksiyonların hangi isimlerden oluştuğunu gösterecektir. Eğer header dosyasını Delphi’ye hatasız aktardık fakat halen fonksiyonun bulunmadığına dair hata alıyorsak demek ki isimlendirmeler yanlış demektir. Bunun için aşağıdaki yöntemi kullanmalıyız:

Gördüğünüz gibi “external” direktifinin hemen sonuna bir boşluk ile beraber bir name direktifi ekledik. Bu “name” direktifi ile DLL’deki fonksiyona direk olarak işaret etmiş oluyoruz. Bu tekniği sadece ihtiyaç dahilinde kullanabilirsiniz. Veya C / C++ ismi size hoş gelmedi ise fonksiyonun ismini Delphi’de kullanım adını değiştirmek için kullanabilirsiniz.

Not
Bir tecrübemi aktarmak istiyorum. Eğer C / C++’a fazla hakim değilseniz, muhtemelen header dosyalarını çeviriken bir çok hata yapacaksınız. Bu durumda DLL’i statik olarak kullandığınızdan dolayı, delphi programı derleyecek ama çalıştıramayacktır. Ve program donacaktır. Çünkü istediği DLL içinde sizin tanımladığınız gibi bir fonksiyon bulamamıştır. Bunun yerine ilk başlarda, header dosyasının çevirimi doğru bir şekilde çevrilene kadar, DLL dosyasını dinamik olarak yükleyin. Bu şekilde çıkan hataları, hangi fonksiyon tanımlamasından kaynaklandığını belirleyebilirsiniz. Dinamik DLL yüklemesinin nasıl yapıldığını internetten araştırarak bulabilirsiniz.
Not
Header dosyalarını çevirmek için aslında JEDI kütüphanesine ait bir araç bulunmaktadır. Fakat bu araç da tam olarak header dosyalarını çevirememektedir. Daha doğrusu yine burada anlattığımız bilgilere ihtiyaç duyacaksınız. Bu araç sadece çok büyük dosyalarda yazım kolaylığı sağlamak açısından bir kolaylık getirmektedir. Ayrıca ileride anlatacğımız konular için bu araç yetersiz kalmaktadır. Bu araca Dr. Bob’un sitesinden ya da JEDI kütüphanesinden erişebilirsiniz. (Header Conversation Tool)

Çağırım mekanizmalarına hakim olmak Delphi çevirimi noktasında size büyük kolaylık sağlayacaktır. Bu yüzden bu konuyu ilk sıraya aldım ve biraz da uzun tuttum.

Veri Tipleri

C / C++ kodları, çok fazla pointer ile ilgili işlemleri barındırmaktadır. Basit bir tip tanımlamasında bile pointerlara ihtiyaç duyarsınız. Fakat C / C++’da bulunan bu pointer kullanımı Delphi’ye geçtiğinde illaki pointer kalacak diye bir şart yoktur. Kullanımda bu olay farklılık göstermektedir.

İlk önce basit veri tiplerinden başlayalım. Aşağıdaki fonksiyona bir göz atalım:

Burada “char*” olarak çıktı veren bir fonksiyonuz mevcut. C’de “*” işareti pointer tanımlamak ve çarpım işlemlerini yapmak için kullanılır. Eğer char, int gibi bir tip ile birlikte kullanılıyorsa bu, pointer operatörüdür. Bu örnekte “char*” ifadesi bir char işaretçisini ifade eder. Bu Delphi’de PAnsiChar ile ifade edilir. PChar demiyorum çünkü Delphi 2009 ile beraber artık PChar unicode oldu. Fakat buradaki “char” ansi olan bir char tipidir. Bunun Delphi karşılığı:

olacaktır. Burada kullanılan C / C++ pointer’ı aynı şekilde Delphi’de de pointer olarak geçmiştir. Fakat bazen C’de pointer’lar hem pointer tanımlamak için, hem dizi tanımlamak için hem de parametrelerde çıkış için kullanılabiliyor. Bunların ayırımını zamanla ve tecrübeyle kazanacaksınız. Aşağıda referans olarak kullanabileceğiniz bir tablo gözükmektedir. Bu tabloyu kullandıkça artık aşina olup tekrar dönüp bakmayacağınızı da zannediyorum. Ama şimdi her birine birer birer göz atmanızda yarar var.

C / C++ Tipi Delphi Karşılığı Delphi 2009 Alternatifi
char AnsiChar
char* PAnsiChar
wchar_t WideChar Char
wchar_t* PWideChar PChar
signed char ShortInt
unsigned char Byte
LPSTR veya PSTR PAnsiChar
LPWSTR veya PWSTR PWideChar PChar
void* Pointer
bool Boolean
float Single
double Double
long double Extended
int Integer
signed int Integer
unsigned int Cardinal
UINT Cardinal
unsigned long Cardinal
unsigned long int Cardinal
unsigned Cardinal
long LongInt
signed long LongInt
long int LongInt
DWORD Cardinal veya DWORD
QWORD QWORD
WORD Word
unsigned short Word
unsigned short int Word
short SmallInt
short int SmallInt
signed short SmallInt

Tabloyu incelerseniz çoğu tipin birbirinin aynısı olduğunu anlarsınız. Bu yüzden tablo biraz uzunca oldu. Bunun nedeni C / C++’da bolca makro denilen yapıların kullanılmasıdır. Makrolar ile ilgili işlemleri ileride anlatacağımızdan şimdilik burada kısa kesiyoruz.

Gördüğünüz gibi string yerine PChar yada PAnsiChar kullanılmakta. Tabloda ayrıca Delphi 2009 ve yukarısında kullanılmak üzere verdiğim alternetifler de mevcut.

Bir Tüyo
Tabi burada verilmeyen bir çok tip olabilir. Ama temel manada bunlar bize referans olacaktır. Diğer tipler için bir tüyomuz şöyle olacaktır. Mesela UINT gibi makro bir tipin ifade ettiği tipi,değeri bulabilmek için C++ Builder gibi herhangi bir derleyeci size kafi gelecektir. Tek yapmanız gereken aşağıdaki gibi bir yapıyı, derleyicinin kütüphane dosyalarında arattırıp bulmanızdır.

C++ Builder için, sadece Ctrl ile tipin üzerine tıklamınız kafidir. Yukarıdaki ifadede UINT makrosu, “unsigned int” olarak tanımlanmıştır. Geriye kalan sadece “unsigned int” için tablodan Delphi karşılığını öğrenmektir.

Veri tipleri ile ilgili zamanı geldikçe yine değineceğiz. Ama giriş için bu kadarlık bilgi yeterli.

Makrolar

Diyeceksiniz ki, ne oluyor C dersine mi başladık? Eğer bir dilden diğer dile çevirim yapmak istiyorsanız her iki dilin de incelikleri bilmeniz gerekmektedir. Tabi biz burada bir C kitabı yazacak değiliz. Bunun yerine mümkün olduğunca kısa tutup püf noktalarını vermeye çalışıyorum. Fakat, yeri gelecek bir C kitabını karıştırmanız gerekebilecek veya C ile ilgili bir siteyi…

Makrolar C / C++ derleyicilerine, derlemeden hemen önce yapılacak olan işlemleri bildirir. Bir nevi Delphi’deki {$ ..} derleyici direktiflerine benzeselerde bunlar daha karmaşıklardır. Önemli nokta, makroların derlemeden hemen önce çalıştırılmasıdır ve derlemeye dahil olmamasıdır. Bu yüzden C / C++ derleyicileri precompile denilen bir işleme tabi tutulurlar. Bu da C / C++ derleyicilerinin neden bu kadar yavaş derlediklerinin bir sebebidir. Eğer C / C++ ile büyük bir programı derlememiş iseniz hala, Delphi gibi 1-2 sn içinde derlediğini zannedersiniz. Halbuki C/C++’da ömrünüz yarısı derlemekle geçer 🙂

Aşağıda tanımlı basit bir makro görüyorusunuz:

Makro burada gördüğünüz gibi #define ile tanımlanıyor. Delphide olduğu gibi #ifdef, #ifndef, #endif gibi ifadelerle bu makronun tanımlı olup olmadığı kontrol edilebilir.

Peki bu makro delphi’ye geçirilecek mi? Belki evet belki hayır. Eğer makro bir fonksiyonu tanımlıyorsa bu durumda makroyu delphide tanımlamalısınız. Aksi taktirde makronun değeri sizin için yeterlidir. Makroyu geçrimenize gerek yok.

Eğer önceki konudaki tüyoyu okudu iseniz makroların gerçek değerlerine nasıl ulaşacağımızı biliyoruz. Mesela aşağıdaki makroyu birebir delphi’ye geçirmeye luzum yoktur:

C:

Delphi:

Ama isterseniz size_t makrosunu bir tip olarak tanımlayabilirsiniz de:

Ama lüzum yok. Peki hangi makroları delphi’ye çevirmemiz gerekli? Şimdiye kadarki tecrübeme göre genelde fonksiyon makrolarını geçrimek yeterli. Aşağıda örnek bir fonksyion makrosu mevcut ve devamında delphi kodlarını bulabilirsiniz:

Gördüğünüz gibi sadece “inline;” olarak tanımlamamız aynı etkiyi yapacaktır. Çünkü “inline” direktifi de makro gibi fonksiyonun çağrıldığı yerde çalıştırılır. Inline ve makro fonksiyonlar için internette bir çok makale bulabilirsiniz.

Bunun dışında makrolar ile iligli olarak şunu söylemek istiyorum. Önceden de dediğim gibi her makronun bire bir Delphi’ye çevrilmesine gerek yoktur. Makro fonksiyonların haricinde bir de bazen makro sabitler de tanımlanabilir. Mesela:

Bu tanımlamaları ister const ile tek tek eşitleyerek yaparsınız isterseniz enumerator tanımlarsınız. Biz ikisini de görelim:

Tercih size kalmış…

Çok karmaşık makrolar geldiğinde internetten veya bir c kitabından yardım alabilirsiniz. Fakat bu kadarlık bilgi sizi fazlasıyla idare edecektir.

Gelecek Makalede

Daha yapacağımız çok işler olacak. Şimdilik bu verdiğimiz bilgiler ile kendiniz çevirimler deneyebilirsiniz. Fakat, daha görememiz gereken çok önemli konular mevcut. Özellikle fonksiyon parametreleri başlı başına bir konu başlığı.

Bununla beraber bu makale serisinde sadece DLL kullanımını görmeyeceğiz. Gelecek makalelerde DLL kullanmadan C obje dosyalarını direk olarak delphi’ye gömeceğiz. Böylece programınızın yanında ek bir DLL verme zorunluluğunuzda kalkacak. Tabi bu konu başlı başına bir makale bölümü olacaktır.

Yine gelecek makalelerde hedear dosyaları haricindeki, implementation olarak ifade ettiğimiz kısımları da sıfırdan Delphi’ye nasıl çevrileceğinden bahsedeceğiz. Daha doğrusu yine bazı püf noktalara değineceğiz. Yoksa tüm gramerin nasıl çevrileceğini anlatmak biraz uzun ve sıkıcı olabilir.

Bu bölümlük bu kadar.

Fikir, eleştiri ve önerilerinizi bekliyorum.

Fatih Tolga Ata – 2009

» Tags: , ,

17 Comments

  • At 2009.02.19 09:51, Murat said:

    Merhaba Fatih bey,

    Güzel bir konuya çok güzel bir anlatımla değinmişsiniz. Ellerinize sağlık.

    İyi çalışmalar

    • At 2009.02.19 13:49, Fatih Tolga Ata said:

      Teşekkür ederim Murat bey,
      Çalışmalarınızda başarılar dilerim.

      • At 2009.03.08 19:46, sadettinpolat said:

        cok guzel ve faydali bir makale olmus. tesekkur eder calismlarinizda basarilar dilerim. elleriniza saglik…

        • At 2010.02.14 04:59, arif said:

          maşallah, çok güzel, çok kaliteli bir makele olmuş eline sağlık.

          • At 2010.02.24 17:43, OSMAN said:

            C++ da unsigned char * ImageBuffer;
            Delphi 7 ye bu kodu nasıl uyarlayabilirim;
            Saygılarımla

            • At 2010.02.24 17:58, Fatih Tolga Ata said:
              type
                TUnsignedCharArray = array of Byte; //Veya Char
              var
                ImageBuffer: TUnsignedCharArray;
              begin
                //Kullanmadan önce boyut ataması yapmanız gerekmekte.
                SetLength(ImageBuffer, 15); //gibi...
              

              Kolay gelsin

              • At 2011.12.19 02:17, Gökhan said:

                Merhaba Fatih Bey,
                Delphide yeniyim. Üzerinde çalıştığım bir proje var ve ben bu proje kapsamında grafik çizimlerini (özellikle 3D) başarmak zorundayım.
                Şimdilik internetten edindiğim Bresenham’ın algoritmasını temel alan C kodlarıyla yazılmış bir çalışma var elimde. Bugünlerde onun üzerinde çalışıyorum ve şuan sadece 2 kısmı başarıyla sonuçlanmış ancak tamamı 4 kısımdan oluşan program içerisinde çıldırmak üzereyim..! 🙂
                Söz konusu dökümanlarda bir line, bir circle, bir ellipse ve birde Bézier curve çizilmek istenmiş.
                Ben C kodlarını Delphiye dönüştürürken ilk ikisini başardım ancak diğer ikisinde bir türlü çizim yaptıramadım 🙁
                Bu konuda bana yardımcı olabil misiniz?
                Sözkonusu çalışmanın proje dosyalarını ve kaynak pdf’i ekliyorum. Bir inceleyin bakalım yüzümü güldürmek isterseniz bana mail aracılığyla ulaşabilirsiniz. Ve eğer bana ulaşırsanız çok sevindirirsiniz. 🙂
                http://www.4shared.com/file/WC7DUau8/butterfly.html
                http://www.4shared.com/document/4cDI9ifa/Bresenham_1.html

                • At 2012.06.22 17:58, termo said:

                  merhaba üstad,

                  c de
                  char** buf
                  şeklinde bir değişken var.bunun delphi karşılığı nedir?şimdi örnek c kodunu şöyle:

                  EXTERN bool readRec(char* ip, unsigned char start_tm_year, unsigned char start_tm_mon, unsigned char start_tm_day, unsigned char stop_tm_year, unsigned charstop_tm_mon, unsigned char stop_tm_day, char** buf, int& len);
                  Input Parameter: ip: machine ip address
                  start_tm_year, start_tm_mon, start_tm_day:start date Y/M/D
                  stop_tm_year, stop_tm_mon, stop_tm_day:stop date Y/M/D
                  Output Parameter:buf:read data-stored address len: read the data length
                  Return Value: true: read successfully false: read failed
                  performance function:read attendance records

                  c de kullanımı:

                  typedef bool (*func_readRec)(char* ip, unsigned char start_tm_year, unsigned char start_tm_mon, unsigned char start_tm_day,
                  unsigned char stop_tm_year, unsigned char stop_tm_mon, unsigned char stop_tm_day,
                  char** buf, int& len);

                  char* pRecvBuff = NULL;
                  //char** pRecvBuff = NULL;
                  int nReadLen = 0;

                  if(var_readRec(pDestIP, systmLog.start_tim_year, systmLog.start_tim_mon, systmLog.start_tim_day,
                  systmLog.end_tim_year, systmLog.end_tim_mon, systmLog.end_tim_day,

                  &pRecvBuff, nReadLen) ) //»ñÈ¡º¯ÊıµØÖ·³É¹¦
                  {
                  MessageBox(“read record is ok, Çë²éÔÄtxtÎļş!”);
                  }
                  else
                  {
                  MessageBox(“read record is err!”);
                  }

                  bunu delphiye dönüştürmeye çalıştım:

                  function readRec(ip:string;start_tm_year:Word;start_tm_mon:Word;start_tm_day:Word;
                  stop_tm_year:Word;stop_tm_mon:Word;stop_tm_day:Word;var buf:Pointer;var len:integer):Boolean; cdecl; external ‘fcomm.dll’;

                  //———————————delphi kullanımı

                  nReadLen:=0;

                  readRec(IPAddress,start_tm_year,start_tm_mon,start_tm_day,stop_tm_year,stop_tm_mon,stop_tm_day,@buf,nReadLen);

                  memo1.text:=buf;

                  yani burada buf ve nReadLen tip tanımlamalarını yapamadım.c fonsiyonunda pointer falan var,orayı çözemedim.burada buf değişkenine dolduran değeri bir memo ya yazdırmam lazım.fonsiyonda en sondaki buf ve nReadLen tanımlarını delphiye nasıl dönüştürülür?

                  Teşekkürler.

                  • At 2012.06.22 20:36, Fatih Tolga Ata said:

                    Açıkcası kodlarınızın hepsini incelemeye vaktim yok. Ama makaleyi okumuşsanız göreceksiniz ki char* karşılığı PAnsiChar’dır, tabi char unicode ise ve Delphi 2010’dan sonraki versiyona dönüştüryorsanız PChar olur. char** ise genelde array için kullanılır. Genelde diyorum çünkü istisna da olabilir. Array olarak düşünürsek:

                    type
                      TArrayOfPChar = array of PAnsiChar; //Char unicode değilse!!
                    var
                      buf: TArrayOfPChar;
                    begin
                      //Kullanmadan önce boyut ataması yapmanız gerekmekte.
                      SetLength(buf, 15); //gibi...
                    end;
                    

                  • At 2012.06.23 10:36, termo said:

                    maalesef TArrayOfPChar = array of PAnsiChar; yaptığım zaman buf değişkeni içine anlamsız rastgele karakterler geliyor.c de char* , delphide string tipine karşılık gelir.

                    bu fonksiyon ne işe yarıyor,onu izah edeyim:ip değişkenine girilen ip adresli cihaza bağlanıp cihazdaki verileri buf değişkeni içine dolduruyor.(c fonksiyonundaki , char** buf, int& len); ifadesinden böyle anladım.)
                    benim de buf değişkeninden bu değerleri alıp string formatta memo1 içine almam gerekiyor.

                    bir çözüm yolu olması lazım.???? yada bana mail atın bu sorunu çözelim, çok zaman alacak zor bir şey değil,tek sorun c deki

                    , char** buf, int& len);

                    delphi karşılığını bulmak.

                    teşekkürler.

                    • At 2012.08.01 21:19, Fatih Tolga Ata said:

                      Rastgele karakterlerin gelmesi unicode/ansi uyumsuzlupu diyebilirim. Ama uygulama üzerinde debug yapmadan kesin bir şey söyleyemem. char*’ın string olma hadisesine gelince, bu yalnış. char* => PChar ya da PAnsiChar olur, tabi ki yine dediğim gibi unicode olmasına göre bu değişir. Neden string ile aynı değil? Cevap olarak null-terminated string’lerin ne olduğunu araştırmanızı öneririm.
                      char** fonksiyon içerisinde nasıl kullanıldıını görebiliyor musunuz? Eğer string’in bir karaketerine erişir gibi karakterlere erişiliyorsa bu durumda üstte verdiğim gibi PChar ya da PAnsiChar array olur. Debug yaparak gelen verilerin ascii code karşılıklarına bakın. Eğer unicode ise genelde 00 A1, 00 54, 00 60 gibi başında 00 olarak gelir. Yani 2 byte olacak şekilde… Eğer utf8 ise şu anda hatırlamıyorum ama bazı karakterlerin başına bir şey gelmezken bazılarına özel değerler eklenerek karakter oluşturulur. Eğer utf8 ise biraz uğraşmanız gerekecek.

                    • At 2012.06.27 17:04, ibrahim SARI said:

                      Üstad size nasıl ulaşabilirim ?

                      • At 2012.08.01 21:22, Fatih Tolga Ata said:

                        twitter üzerinden direk mesaj atabilirsiniz. Buraya email’den daha çok bakıyorum çünkü. twitter.com/FatihTolgaAta

                      • At 2012.06.28 11:45, termo said:

                        merhaba ibrahim bey,

                        hem c hem de delphi ye hakim olmalısınız.sorun şu:
                        mesala c de char* , delphide string tipine karşılık gelir. ama gerçekte char* bir pointerdır.yani
                        char* buf; //c
                        buf:string; //delphi
                        gibi oldukça basit bir çevrim işi çözüyor.ama
                        char** buf;
                        nasıl dönüştürülür,onu bulamadım…

                        mail adresim: mainnet11@yahoo.com

                        teşekkürler.

                        • At 2016.12.22 21:15, İbrahim said:

                          Merhaba;
                          Siz burada .dll dosyalarından bahsetmişsiniz lakin benim elimde .h dosyaları ve .a dosyaları (static linking) var. Bu .a dosyalarını bu .dll dosyaları gibi nasıl kullanacağım? (Elimde olanlar sadece .h ve .a dosyaları, kaynak kod kapalı).

                          Ayrıca C++ tarafında yazılmış Message adlı sınıfı başka bir fonksiyon parametre tipi olarak almış. Bu tipi Delphi fonksiyonuna parametre tipi olarak nasıl atabilirim? Teşekkürler!

                          • At 2016.12.22 21:19, İbrahim said:

                            Örnek olarak .h dosyasında şöyle bir kod parçası mevcut:
                            void Send(const Message& message);
                            Buradaki Message tipini Delphi’ye nasıl aktaracağım?

                            • At 2016.12.23 15:23, Fatih Tolga Ata said:

                              açıkcası bununla uğraşmayalı çok uzun zaman oldu. ama şöyle bir şeyler vardı belki işinizi görür: https://sourceforge.net/projects/jdarth/

                              (Required)
                              (Required, will not be published)