2013-03-08 15 views
5

C++/CLI'den yönetilmeyen bir API kullanmam gerekiyor. Bu API, boş bir işaretçiyi keyfi kullanıcı verilerine ve birkaç geri aramaya depolar. Daha sonra bu geri aramaları, kullanıcı verilerini void * olarak geçirerek çağırır. Ben çalışıyorumgcroot güvenli kullanım mı?

static void __stdcall Callback(void* userData) { 
    ((MyType*)userData)->Method(); 
} 

class MyType { 
public: 
    MyType() { RegisterWithApi((void*)this, Callback); } 
    void Method(); 
}; 

:

Şimdiye kadar yani kullanıcı veri olarak onun "bu" işaretçi geçirerek ve bu sınıfa geri API çağrısı yapmak o işaretçi kullanarak yerel bir sınıf vardı Bunu yönetilen bir sınıf kullanarak çevir. Ben işte ben şimdi yapıyorum nasıl yazın gcroot güvenle yerli kodunda bir yönetilen referans olarak saklamak için kullanılabileceğini bulundu:

// This is called by the native API 
static void __stdcall Callback(void* userData) { 
    // Cast back to gcroot and call into managed code 
    (*(gcroot<MyType^>*)userData)->Method(); 
} 

ref class MyType { 
    gcroot<MyType^>* m_self; 
public: 
    MyType() { 
     m_self = new gcroot<MyType^>; 
     RegisterWithApi((void*)m_self, Callback); 
    } 
    ~MyType() { delete m_self; } 
    // Method we want called by the native API 
    void Method(); 
} 

bu C++/CLI derleyici iyi gibi geliyor olsa da, ben değilim mükemmel bir şekilde güvence verdi. Anladığım kadarıyla, gcroot bir şekilde yönetilen referansını GC tarafından taşındığından takip ediyor. Yönetilmeyen kod tarafından bir void * olarak saklanırken bunu başaracak mıdır? Bu kod güvenli mi?

Teşekkürler.

+1

Marshal :: GetFunctionPointerForDelegate() 'i bir iyilik yapın, bir örnek [burada] (http://stackoverflow.com/questions/2972452/c-cli-pass-managed-delegate-to-unmanaged-code/2973278#2973278) –

cevap

2

'da yönetilen türden bir yöntemi çağırır. Bu, yaptığım işte mükemmel sonuç verir. Gcroot'un amacı, yönetilen bir referansı yerel yığın üzerinde depolamaktır, ki burada yaptığım şey tam olarak budur.

0

Hayır! Tam olarak başka bir yol var. gcroot bir yerel sınıf şablonudur. Clr desteğiyle derlenen yerel bir türdeki yönetilen belleğe bir tutacak depolamak için kullanırsınız. Genellikle, çağrıları yerel bir nesnenin üye işlevlerine, gcroot türünde bir üyede saklanan yönetilen bir nesneye yönlendirmek için kullanırsınız.

DÜZENLEME: kod örneklerini yazarak biraz garip mobil dün oldu ... gcroot<T^> amaçlanan ve tipik kullanım bu doğrultuda bir yerdedir:

// ICallback.h 
struct ICallback { 
    virtual void Invoke() = 0; 
    virtual void Release() = 0; 
    protected: 
     ~ICallback() {} 
}; 

ne native uygulamaları veya kütüphaneler bakın ve ekleyin.

Sizin yerli uygulamalar CreateCallback diyoruz
// Callback.cpp (this translation unit must be compiled with /clr) 
// I did not compile and test, but you get the point... 
template<class T^> class Callback : public ICallback { 
    gcroot<T^> m_Managed; 

    virtual void Invoke() 
    { 
     m_Managed->Invoke(); 
    } 

    virtual void Release() 
    { 
     delete this; 
    } 
public: 
    Callback(T^ p_Managed) : m_Managed(p_Managed) {} 
}; 

__declspec(dllexport) ICallback* CreateCallback() 
{ 
    auto t_Managed = gcnew SomeManagedType(); 
    return new Callback<System::Action^>(
     gcnew System::Action(t_Managed, &SomeManagedType::Method)); 
} 

, ICallback bir örneğini aldığınızda Invoke -d: Sonra ICallback uygular ve gcroot<ManagedType^> bir bazı yönetilen nesne için bir tanıtıcı depolayan CLR desteği ile derlenmiş karışık bileşeni var gcroot<System::Action^> ...

+1

Yani sorun, yerel API'nın clr desteği ile derlenmemesidir? Çünkü başka türlü tanımladığın şey tam olarak ne yaptığım. – Asik

+0

gcroot kullanan yerel sınıf, clr desteği ile derlenmelidir. Açıkladığım şey tam olarak sorunun içinde gösterdiğinizin tam tersi: yönetilen bir nesnede yerel bir gcroot işaretçisini saklıyorsunuz. –

+0

Peki, gcroot'un kullanıldığı işlev ("Geri arama") * CLR desteğiyle * derlenmiştir. Gcroot görünüşte izin verilen yönetilmeyen yığın üzerinde saklanır. Yönetilen bir sınıfın buna bir işaretçi tutması ne gibi bir fark yaratır? – Asik