2

Many articles including here, have shown me how to make C++/CLI delegates for use as C++ callback:

typedef void(*SDKUnManagedCB)(void * c, void *c2);

LATER...

[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
delegate void sdkCBStyle(void * c, void *c2);

LATER...

sdkCBStyle^ users = gcnew sdkCBStyle(this, &SDK::UsersCB); //2nd parameter is method here in CLI file
IntPtr pUsers = Marshal::GetFunctionPointerForDelegate(users);
GC::KeepAlive(users);  //freed later
GetUsers(static_cast<SDKUnManagedCB>(pUsers.ToPointer())); //GetUsers is unmanaged 3rd party API

My question is, I have about 20 callbacks with the same signature and I'd like to simplify the complicated CLI code. I'd like to do something like this:

GetUsers(CreateCallBack(&SDK::UsersCB));
GetActions(CreateCallBack(&SDK::ActionsCB));
//etc

Problem is I can't find the proper function signature for passing that function name. F12 (Go to Definition) goes to definition of delegate Intellisense also shows that function signature

MSDN has two protected constructors both take a String as the second parameter I tried to use

Delegate(Object, String)

But when I try:

SDKUnManagedCB CBCreator(String method) {
sdkCBStyle^ piCB = gcnew sdkCBStyle(this, method); // yes my variable names suck...

Real time compile has shows an error tooltip:

Error: invalid delegate initializer -- must be a function

I tried to look into CreateDelegate but this looks really slow

SDKUnManagedCB CBCreator(String^ method) {
    MethodInfo^ info = GetType()->GetMethod(method, BindingFlags::Public | BindingFlags::Instance);

    sdkCBStyle^ piCB = static_cast<sdkCBStyle^>(Delegate::CreateDelegate(sdkCBStyle::typeid, info)); 
    GC::KeepAlive(piCB);   // Yes this is a known leak, it will have to be stored as a member and explictly freed
    return  static_cast<SDKUnManagedCB>((Marshal::GetFunctionPointerForDelegate(piCB)).ToPointer());

}

Called with:

GetObjects(CBCreator("ObjectCB"));

Looks like it compiles, but is there an easier way?

EDIT: It crashes at runtime, An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll Additional information: Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.

Do i need more binding parameters; the callback has to be a member function for data encapsulation

Community
  • 1
  • 1
David
  • 437
  • 4
  • 12
  • Delegate type safety is critical, there is no commonality if the callback function pointer signatures are not the same. Whether there is any is impossible to tell from the question. If it is slow then just store the delegate objects so you can use them again later, also avoids the bug in the GC::KeepAlive() placement you now have. – Hans Passant May 27 '15 at 15:52
  • @HansPassant yes for brevity (and hacking major functionality) i kept out the proper memory management of my delegate handles. I don't understand the rest of your point; I explicitly stated I had 20 callbacks with the **same** function signature. Also see my edit, it currently doesn't work so the performance issue will have to wait. – David May 27 '15 at 16:02

0 Answers0