views:

155

answers:

2

Hi all,

I'm trying to add some managed code into an existing c++ GUI application. I'd like to get a functional callback working...specifically, I'd like to pass a method pointer from UNMANAGED code to MANAGED code and have the managed code invoke the callback.

I'm looking at something like this:

typedef int (__stdcall *ANSWERCB)(int);  //Delegate declaration

class UnmanagedObject
{
public:

 UnmanagedObject() {}
 int MethodD(int n) { return n; }
};

with a corresponding managed class:

public delegate int CallbackDelegate(int i);

public class ManagedClass
{
    public ManagedClass() {}
    public void MethodD( CallbackDelegate cd ) { cd.Invoke( 5 ); }
}

The problem is that I can't for the life of me figure out how to actually invoke this from managed code:

UnmanagedObject* obj = new UnmanagedObject();
ManagedLibrary::ManagedClass^ mc = gcnew ManagedLibrary::ManagedClass();
mc->MethodD( /* what do I pass here? */ );

I've tried:

ManagedLibrary::CallbackDelegate^ cd = gcnew CallbackDelegate(obj, &UnmanagedObject::MethodD);

but it generates a compiler error "delegate target needs to be a pointer to a member function".

Any interop guru's able to help out?

Thanks!

A: 

Half your trouble is that the member function in question doesn't actually have the same signature as the callback delegate. It takes a function pointer itself. First, you need to alter UnmanagedClass to be

class UnmanagedObject
{
public:
    UnmanagedObject() {} 
    int MethodD(int n) { return n; } 
};

I suspect for the gcnew call that you simply have the parameters the wrong way around- i.e., mem func ptr, then obj.

DeadMG
You're right - I've fixed the unmanaged class. However, the error remains the same.
Mark
+1  A: 

The problem starts at your ANSWERCB function pointer declaration. It isn't actually suitable for calling the MethodD() function, that's an instance method of the class. Make this work in native C++ first, you need a member function pointer.

From there, you'll have a lot less problems making it work from managed code, Marshal::GetDelegateForFunctionPointer() gets you what you need.

Hans Passant