Search code examples
eventsc++-climanaged

Firing events from a unmanaged function


I am trying to fire an event from a unmanaged function using a pointer to managed object. I get the following error:

error C3767: 'ShashiTest::test::OnShowResult::raise': candidate function(s) not accessible

How ever I can call regular function ShowMessage without any issue?

#pragma once

#using<mscorlib.dll>
#using<System.Windows.Forms.dll> 

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Diagnostics;
using namespace System::Windows::Forms;

namespace ShashiTest {
    public delegate void ShowResult(System::String^);

    public ref class test
    {
    public:
        event ShowResult^ OnShowResult;
        test(void)
        {
        };
        void ShowMessage()
        {
            MessageBox::Show("Hello World");
        }
    };

    class ManagedInterface
    {
    public:
        gcroot<test^> m_test;
        ManagedInterface(){};
        ~ManagedInterface(){};

        void ResultWindowUpdate(std::string ResultString);
    };
}

void ShashiTest::ManagedInterface::ResultWindowUpdate(std::string ResultString)
{
    if(m_test)
    {
        System::String ^result = gcnew system::String(ResultString.c_str());
        m_test->OnShowResult(result);
    }
}

Solution

  • You can do this by manually defining the event, and changing the access level of the raise() portion to internal or public. (The default is either protected or private -- see the post by ildjarn at http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/ff743ebd-dba9-48bc-a62a-1e65aab6f2f9 for details.)

    The following compiled for me:

    public ref class test
    {
    public:
        event ShowResult^ OnShowResult {
            void add(ShowResult^ d) {
                _showResult += d;
            }
            void remove(ShowResult^ d) {
                _showResult -= d;
            }
        internal:
            void raise(System::String^ str) {
                if (_showResult) {
                    _showResult->Invoke(str);
                }
            }
        };
        test(void)
        {
        };
        void ShowMessage()
        {
            MessageBox::Show("Hello World");
        }
    private:
        ShowResult^ _showResult;
    };
    

    An alternative would be to define a helper function that would fire the event.