许多文章,包括here, 向我展示了如何使用C ++ / CLI委托作为C ++回调:
typedef void(*SDKUnManagedCB)(void * c, void *c2);
后...
[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
delegate void sdkCBStyle(void * c, void *c2);
后...
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
我的问题是,我有大约20个具有相同签名的回调,我想简化复杂的CLI代码。我想做这样的事情:
GetUsers(CreateCallBack(&SDK::UsersCB));
GetActions(CreateCallBack(&SDK::ActionsCB));
//etc
问题是我找不到传递该函数名的正确函数签名。 F12(转到定义)转到委托的定义 Intellisense还显示了函数签名
MSDN has two protected constructors都将String作为我尝试使用的第二个参数
Delegate(Object, String)
但是当我尝试时:
SDKUnManagedCB CBCreator(String method) {
sdkCBStyle^ piCB = gcnew sdkCBStyle(this, method); // yes my variable names suck...
实时编译显示错误工具提示:
Error: invalid delegate initializer -- must be a function
我试图调查CreateDelegate,但这看起来很慢
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());
}
跟:
GetObjects(CBCreator("ObjectCB"));
看起来它编译,但是有更简单的方法吗?
编辑:它在运行时崩溃了, mscorlib.dll中出现未处理的“System.ArgumentException”类型异常 附加信息:无法绑定到目标方法,因为其签名或安全透明度与委托类型的方法不兼容。
我需要更多的绑定参数;回调必须是数据封装的成员函数