Eğer C ve C++ ile uzun zamandır uğraşıyorsanız gösterge(pointer) kavramını biliyorsunuz demektir. C++ standardında bulunan std::auto_ptr akıllı gösterge sınıfı ile kendi tasarlardığımız sınıfları belleğe yükleyip gerisini düşünmeden kullanabiliyoruz ama ya C++/CLI de ne yapacaz. Sürekli derleyici hatalarıyla karşılaşmak istemeyen kullanıcılar nasıl bir yol izlemeliler. Bunu sürekli kodlama yaparken keşfettim. Aslında Keny Kerr in (blog.asp.net sitesinde bakabilirsiniz) bununla ilgili örnek olarak tasarlanmış bir sınıf bulunmasına rağmen derleme işleminde ayrıca çalışma esnasında hata verdiğini görünce bende kendi tasarladığım akıllı gösterge sınıfımı kullanayım dedim. Neyse bu kadar açıklamadan sonra kodlarımıza geçelim.
Şimdi C++.NET eğer Visual Studio 2005 sürümlerinden herhangi birini kullanıyorsanız cli, cli:pure, ve cli
afe derleme seçeneklerini sunduğunu göreceksiniz(Project Properties ten Common Language Support kısmından bakabilirsiniz).cli derleme seçeneği IJW yani it just works mantığıyla çalışıyor.
Yapmış olduğu iş ise System.Runtime.InteropServices.GCHandle yapısını kullanarak bellekteki sınıfını adresini alıp argüman olarak atamak yada artık nasıl kullanıyorsanız değer gibi mesela bunun gibi işlemlerde adresle ilgili işlemleri yapmaktır. Peki bu nasıl oluyor. İşte böyle
ref struct Sallama
{};
Sallama s;
Şimdi kullanıım:
GCHandle g = GCHandle::Alloc(s);
sırada adresi alma var.
sınıfımıza geçelim:
using namespace System;
template<class T>
public ref class Memory
{
public:
// Her zamanki gibi kurucu metodumuz
Memory( T* t ) : t_( t )
{}
// Akıllı gösterge sınıfı metodları ve operatörlerimiz
T* operator->() { return t_; }
void operator=(T* t) { t_ = t; }
void release() { delete t_; OnDone = true; }
bool ValidPointer() { return ( t_ != nullptr ); }
// AA, AA. Acaba bu da ne. Aşağıdaki metod aslında
//System::IDisposable interface için bellekten silinme metodu
// Eğer c# programlıyorsanız ozaman using kelimesini hatılıyacaksınız. Tabiki namespace eklemek için gerekli olanı değil
// Oda şöyleydi using(SqlConnection c = new SqlConnection) {}...
!Memory() { release(); }
// Bellekten silinme metodumuz.
~Memory() { if ( !OnDone ) release(); }
private:
// Native sınıfları kullanmak için tuttuğumuz değişkenimiz
T* t_;
// Burda göstergenin silinirken gerçekte silinip silinmediği ve hata çıkarmadığını anlamak için tuttuğumuz değişken
bool OnDone;
};
Şimdide bir örnek yapalım
Aşağıda NativeCpp class ımız var
class native
{
public:
void Selamla() { System::Console::WriteLine("Native::Selamla()== 'Selam'"); }
};
[COLOR=#c5003f]C++/CLI için iki tane giriş metodu vardır.Bunlardan bir tanesi int main() bu standarttır.
İkincisi int wmain() bu unicode için gerekli (aslında gereksiz çünkü uygulamayı mscorlib.dll yüklediği için...) işte burada dikkat edilmesi gereken nokta wmain kullanırken parametre kullanamıyor olmamız yani main fonksiyonu tanımlarken int main(int argc, char* argv[]) kullanılırken wmainde int wmain() işte böyle. Yoksa derleyici hatası alırsınız çok uğraştırır ilk başta.
Gelelim CLInin standart yükleme fonksiyonuna oda şöyle int main(cli::array<System::String^>^ args). Bu fonksiyon normaldede kullanılmaz sadece CLI derlemelerinde dikkatinizi çektiyse kullanılıyor.
Şimdide ana metodumuz:
int main()
{
// memory sınıfı belleğe bağımsız sınıfı yüklemek için kullanılıyor
Memory<Native> m( new Native() );
// Şimdi Native sınıfının Selamla metodunu çağırıyoruz.
m->Selamla();
// Memory sınıfını bellekten siliyoruz.
m.~Memory(); // Otomatik olaran Native sınıfımızda siliniyor.
}
Eğer Native sınıfımız silinmediyse ozaman şöyle bir fonksiyon yazıp bir daha deneyin.
~Native() { System::Console::WriteLine("Destructor called at {0}", System.DateTime.Now->ToString("F")); }
Sonra bir daha deneyin
m.~Memory();
![[Resim: 114ld.jpg]](http://b1112.hizliresim.com/s/c/114ld.jpg)