Is this using gcroot safe?

I need to use the unmanaged API from C ++ / CLI. This API stores a void pointer to arbitrary user data and multiple callbacks. Then it calls these callbacks, passing the user data as void *.

So far, I had my own class, passing its "this" pointer as user data and using this pointer to call the API in this class, that is:

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

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

I am trying to translate this using a managed class. I found that the gcroot type can be used to safely store a managed link in its own code, so now, as I do it now:

// 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();
}

++/CLI, . , , gcroot - , GC. , * ? ?

.

+5
2

, , . gcroot - , .

+2

! . gcroot - . , clr. - , gcroot.

EDIT: , ... gcroot<T^> - :

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

, . , CLR, ICallback gcroot<ManagedType^>:

// 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)); 
}

CreateCallback, ICallback, , Invoke -d , gcroot<System::Action^>...

0

All Articles