Thread overview
C++ ile Object Pascal İçin Kod Yazarken Merak Ettiklerim
Dec 29, 2016
İbrahim
Dec 29, 2016
erdem
Jan 02, 2017
İbrahim
December 29, 2016

Selamün Aleyküm;

Altta bağlantısını vermiş olduğum siteden yararlanarak Object Pascal'dan C++ kodu çağırmaya çalışıyorum. Lakin burada da görüldüğü üzere şu sualler aklıma takıldı:
Bağlantı Adresi: http://rvelthuis.de/articles/articles-cppobjs.html

'1-)' İlk örnekte görüldüğü gibi bir C++ sınıfı yazılmış (Console sınıfı) ve alt tarafta da bu sınıf özelliğini kaybederek 'extern "C"' ile saf fonksiyonlar yazılmış. Acaba bu şekilde değil de C++ sınıfını yazıp başka bir dilde 'extern "C"' kullanmadan direk bu sınıftan nesne üretip kullanabilir miyiz? Misal olarak:

/* Bu sınıf için extern "C" kullanmadan başka dilde bu sınıfı kullanabilir miyiz? */
class Console
{
public:
 int get_int(int n) { return n; }
 std::string get_str(const std::string& str) { return str; }
 static void write(const std::string& str) { std::cout << str << '\n'; }
};

/* --- Misal Delphi'de şu şekilde direk kullanabilir miyiz? : --- */

var
 cons : Console;

 i : Integer;
 s : String;
begin
 i := cons.get_int(777);
 s := cons.get_str('Hello World!');
 Console.write('--- String ---');
end;

'2-)' "Using COM-style interfaces" başlığı altında:

struct __declspec(uuid("{9BBDA1A4-21E7-4D11-8F1C-E2AD13D2779C}"))
   IConsole : public System::IInterface

Bu satırda uuid ile benzersiz bir id oluşturulmuş. Peki bu id'yi neye göre yazmışlar? Mesela ben 32 karakter sayısını bozmadan misal şöyle kafadan bir id oraya yazsam olur mu? : '"{7V9NCC32-4629-GOO1-P2P1-B036LGA299ZX}"'. Eğer kafadan yazamıyorsak nasıl böyle bir değer elde edebiliriz?

'3-)' Yine 2. sualimle ilgili olarak bu id değeri tam olarak kod içinde ne işe yarıyor? Ayrıca bu kod nasıl çalışıyor?

'4-)' __cdecl, __stdcall ve __fastcall tam olarak ne oluyor? Bunları biraz araştırdım lakin neden bu şekilde ayrı ayrı anahtar sözcükler oluşturmuşlar ve niçin bunları kullanmamız gerekiyor, bunların yanıtını tam olarak bulamadım.

Teşekkürler!

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

December 29, 2016

Alıntı (İbrahim):

>

'1-)' İlk örnekte görüldüğü gibi bir C++ sınıfı yazılmış (Console sınıfı) ve alt tarafta da bu sınıf özelliğini kaybederek 'extern "C"' ile saf fonksiyonlar yazılmış. Acaba bu şekilde değil de C++ sınıfını yazıp başka bir dilde 'extern "C"' kullanmadan direk bu sınıftan nesne üretip kullanabilir miyiz?

Burada anlatıldığına göre bir C++ sınıfını kullanmak için ilkönce C ile sarıcı işlevler yazmak gerekiyormuş.

http://leonardorame.blogspot.com.tr/2011/02/working-with-c-dlls-from-objectpascal.html

Ben de ufak bir örnek yazdım.

#include <cstring>
#include <iostream>
using namespace std;

class Dunya
{
public:
   Dunya();
   void merhabaDunya(char * ileti);
};

Dunya::Dunya()
{
}

void Dunya::merhabaDunya(char * ileti)
{
   const char * merhaba = "C++'den merhaba!";
   strcpy(ileti, merhaba);
}

extern "C"
{
   void dunyaNesnesiOlustur(void * & dunya)
   {
       dunya = new Dunya();
   }

   void merhabaDunya(void * dunya, char * ileti)
   {
       Dunya * benimDunyam = (Dunya *) dunya;
       benimDunyam->merhabaDunya(ileti);
   }

   void dunyaNesnesiniSil(void * dunya)
   {
       delete (Dunya *) dunya;
       dunya = NULL;
   }
}

Burada sınıfın işlevlerine void * gösterge kullanılarak erişiliyor.

void * genel bir göstergedir. Yani void * türü diğer göstergelere tür dönüşümü yapılmadan dönüştürülebilir.

Derlemek için
'
g++ -fPIC -shared dunya.cc -o dunya.so
'

nm programı ile kütüphane içeriğine bakabiliriz.
'
$ nm dunya.so'
[...]
000007a0 t __do_global_dtors_aux
00001ee4 t __do_global_dtors_aux_fini_array_entry
00002028 d __dso_handle
00001edc t __frame_dummy_init_array_entry
w gmon_start
U __gxx_personality_v0@@CXXABI_1.3
00000835 t __x86.get_pc_thunk.bx
00002030 A _edata
00002038 A _end
00000998 T _fini
0000063c T _init
00002030 b completed.6874
00000710 t deregister_tm_clones
00000873 T dunyaNesnesiOlustur
000008f8 T dunyaNesnesiniSil
000007f0 t frame_dummy
000008ca T merhabaDunya
00000750 t register_tm_clones
U strcpy@@GLIBC_2.0

Alıntı:

>

'4-)' __cdecl, __stdcall ve __fastcall tam olarak ne oluyor? Bunları biraz araştırdım lakin neden bu şekilde ayrı ayrı anahtar sözcükler oluşturmuşlar ve niçin bunları kullanmamız gerekiyor, bunların yanıtını tam olarak bulamadım.

Bunlar MS'e özgü bir takım değişken adlandırma ve geçirme kuralları.

https://msdn.microsoft.com/tr-TR/library/984x0h58.aspx

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

December 29, 2016

Her dil (ve her C++ derleyicisi) kendi calling convention'ını ve ABI'ını tanımlama serbestisine sahiptir. extern "C", bu dilleri ortada buluşturuyor. Onu destekleyen her dil diğerlerini çağırabiliyor. Dolayısıyla, bu durumda extern "C" kullanmak gerekiyor.

D'nin bu konudaki bir üstünlüğü, C++ kodlarını extern(C) gerektirmeden, extern(C++) ile çağırabilmesi.

COM konusunu hiç bilmiyorum ama D'nin özellikle COM arayüzlerini destekleyecek biçimde tasarlandığını biliyorum.

__cdecl, __stdcall ve __fastcall; işlevler çağrılırken parametrelerin nasıl geçirildiklerini, dönüş değerinin nasıl döndürüldüğünü, onlar için çağrı yığıtından (call stack) ayrılan yerin kimin tarafından geri verildiği vs. belirleyen farklı yöntemler. Örneğin, __cdecl C dilinin yaygınlaştırdığı yöntem.

Ali

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

January 02, 2017

Yanıtlarınız için teşekkürler. Anlaşılan extern "C" ile C++ kodlarını sarmalayacağız. Peki mesela C++ ile kodlarken JNI ile Jvm oluşturduğumuzda, başka bir dil tarafından da bu C++ kodunu çalıştırdığımızda doğru bir şekilde çalışır mı?

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

January 02, 2017

O teknolojileri bilmiyorum ama eğer onlar da extern "C" kullanıyorlarsa, evet, onlar da yazdığımız bu işlevleri çağırabilirler.

Ali

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