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

MesaC
MesaC used Ask the Experts™
on
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
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
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.

Author

Commented:
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?

Commented:
What is exactly your purpose?
Making class managed or not is decision which is done according to desired class clients. If CommunicationWrapper is class which is used by unmanaged C++ clients, it should be unmanaged. If it should be used by managed clients, it should be managed. In this case ICommunicationWrapper is also managed class or interface.

BTW, in my first suggestion you can remove all mumbo-jumbo about callback function and replace it with direct function call. The imortant thing is that class which handles managed event must be managed.

Author

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

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial