Search code examples
eventsdelegatesfunction-pointersmanaged-c++

Calling a managed class function from an unmanaged class object


This is a class library clr/c++ project. Class A is unmanaged c++, class B managed c++. I would like to create an object of B from a C# application and call the "void Sign" with that object and catch the StatusEvent in C#. How to call B::Showsts from A::call_A in order to achieve this? Please keep in mind that call_A is called from a delegate of the B class object. Thank you in advance!

public class A{
        public:
            int call_A();
    };
    public ref class B{
        private: 
            A* a1;
    public:
        void Sign(String^ ufile);
        void Showsts(string sts);
        delegate void GetResult(String^);
        event GetResult^ StatusEvent;
        SpyrusLib(void){
            a1=new A();
        }
    protected: ~SpyrusLib(){
            delete a1;
        }
    private:
        String^ str;
        delegate int MySignDelegate(String^);
        int MySign(String^ file);
        void Callbacksign(IAsyncResult ^ar);    
    };
    void B::Sign(String^ ufile){
        MySignDelegate^ signDel = gcnew MySignDelegate( this, &B::MySign );
        AsyncCallback^ cb = gcnew AsyncCallback( this, &B::Callbacksign);
        signDel->BeginInvoke(  ufile , cb, signDel );
    }
    int B::MySign(String^ file){
        stdstr=msclr::interop::marshal_as<std::string>(file);
        a1->call_A(stdstr);
    }
    void B::Showsts(string sts){
            str = gcnew String(sts.c_str());
            StatusEvent(str);
    }
    int A::call_A(string stat){
            ?-Showsts(stat);
    }

Solution

  • I'm not sure it's the best solution but I solved it adding the following things to the classes:

    typedef void (__stdcall * Unmanagedstatus)(string sts);
    using namespace std;
    
    public class A{
        private: 
            Unmanagedstatus sendmsg;
        public:
            int call_A();
            spyrus(Unmanagedstatus unm)
            {
                sendmsg=unm;
            }
    };
    public ref class B
    {
        private: 
            delegate void Managedstatus(string);
            Managedstatus^ managed;
            IntPtr unmanaged;
            A* a1;
        public:
            SpyrusLib(void)
            {
                managed = gcnew Managedstatus(this, &B::Showsts);
                unmanaged = Marshal::GetFunctionPointerForDelegate(managed);
                a1=new A((Unmanagedstatus)(void*)unmanaged);
            }
    }
    int A::call_A(string stat){
        sendmsg(stat); // this will call B::Showsts and the events raised 
              //from Showsts are also working in the C# app
    }