Link to home
Start Free TrialLog in
Avatar of MesaC
MesaC

asked on

Wrapping a managed C# DLL in a unmanaged C++ project

Hi,

I am trying to wrap a managed C# DLL so I can call the DLL in an unmanaged C++ project.  I am using the approach of <gcroot> so I can use a global instance in the unmanaged project.  Everything is working fine except when I’m trying to wrap the Events.  I am receiving a C3364 error, “invalid argument for delegate constructor; delegate target needs to be a pointer to a member function”.   I’m not sure what it’s asking for here.  I would like to trap the event in the C++ class so I can respond accordingly in the unmanaged project.  Below are code snippits from each class I'm using.

//Managed C# DLL - contains delegate/events I want to call
  public class TestingDelegates
  {
        public class ConnectionStartThreadArgs : EventArgs…
 
        public delegate void ManagedEvent(int arg);
        public event ManagedEvent SomeEvent;
        protected virtual void OnStartThreads(object sender, ConnectionStartThreadArgs e)
        {
            if (MethodDelegate != null)
            {
                MethodDelegate(this, e);
            }
        }
    }
//This is the class that is called in the unmanaged code, and is the base class to the CommunicationWrapper that wraps the C# DLL.
//interface…
public class ICommunicationWrapper
{
public:
      //virtual void StartCommunication() = 0;
      virtual void SetIPAddress( CString ip ) = 0;
      virtual CString GetIPAddress() = 0;

      //functions to create the unmanaged instance
      static ICommunicationWrapper      *CreateInstance();
      static void                                  Destroy(ICommunicationWrapper *instance);
};

//C++ Class .h
//Wrapper class
public class CommunicationWrapper : ICommunicationWrapper
{
public:
    gcroot<TestingDelegates ^>  _managedObject;
    void  OnManagedDelegate(System::Object ^ sender,   ManagedLibrary::TestingDelegates::ConnectionStartThreadArgs^ e );
public:
    CommunicationWrapper() { _managedObject = gcnew TestingDelegates(); }

};

//.cpp
void CommunicationWrapper::SetupDelegate()
{
//this line causes a C3364
      _managedObject->MethodDelegate += gcnew ManagedLibrary::TestingDelegates::myMethodDelegate( this, &CommunicationWrapper::OnManagedDelegate );
}


ICommunicationWrapper *ICommunicationWrapper::CreateInstance()
{
      return ((ICommunicationWrapper *)new CommunicationWrapper());
}

void ICommunicationWrapper::Destroy(ICommunicationWrapper *instance)
{
      delete instance;
}
void CommunicationWrapper::OnManagedDelegate(System::Object ^ sender, ManagedLibrary::TestingDelegates::ConnectionStartThreadArgs^ e )
{
}

Any ideas???

Thanks
Avatar of AlexFM
AlexFM

Looks OK, but CommunicationWrapper must be ref class, in this case it should work.
If you need to do this in native class, create instance of managed class, and subscribe to event in it. Then create instance of this proxy ref class inside of unmanaged class, and use C++ callback to get event notification.

typedef void (CommunicationWrapper ::*fPtr)(System::Object ^ sender, ManagedLibrary::TestingDelegates::ConnectionStartThreadArgs^ e);   // callback prototype

ref class ProxyClass
{
    TestingDelegates ^ _managedObject;
    fptr callback;
    CommunicationWrapper* wrapper;

    // subscribe to event here
    // in event handler call callback function:
    (wrapper.*callback)( parameters );
};

public class CommunicationWrapper : ICommunicationWrapper
{
    gcroot<ProxyClass> proxy;

    void OnMangedDelegate(...)
    ...
    proxy = gcnew ProxyClass();
    proxy->callback = OnManagedDelegate;  
    proxy->wrapper = this;
}

Code is not tested, only general idea. If you have problem implementing this, I will post more details.
Avatar of MesaC

ASKER

I tried to put this into place and ran into a problem.  When changing the CommunicationWrapper class to be managed with ref class CommunicationWrapper caused the ICommunicationWrapper to need to be managed, which then caused all kinds of problems.  Can you post those additional details?

ASKER CERTIFIED SOLUTION
Avatar of AlexFM
AlexFM

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of MesaC

ASKER

I finally got your example to work.  Thanks for your help