vel*_*yel 13 c++ objective-c callback member-functions
我在objective-c中有ViewController,我的大部分代码都是c ++(.mm).我想从obj-c(在c ++中)为成员函数设置一些回调,并从c ++中调用它们.像这样的东西(它非常简化):
@interface MyClass
{ }
-(void)my_callback;
@end
@implementation MyClass
-(void)my_callback
{
printf("called!\n");
}
-(void)viewDidLoad
{
// setup_callback( "to my_callback ?" );
}
@end
Run Code Online (Sandbox Code Playgroud)
和:
void setup_callback(void(*func)()) { func(); }
Run Code Online (Sandbox Code Playgroud)
这当然不正确.有什么建议我可以这样做吗?
zne*_*eak 16
你有几个选择.
您可以使用块来传达回调工作.这可能是最简单的解决方案,因为它允许您调用代码而无需将任何参数传递给回调"函数".块使用Clang在C及其所有超集中工作,而Clang ++甚至允许在块和lambdas之间进行隐式转换.
#include <dispatch/dispatch.h>
void setup_callback(dispatch_block_t block)
{
// required to copy the block to the heap, otherwise it's on the stack
dispatch_block_t copy = [block copy];
// setup stuff here
// when you want to call the callback, do as if it was a function pointer:
// block();
}
int main()
{
MyClass* instance = [[MyClass alloc] init];
setup_callback(^{
[instance callback_method];
});
}
Run Code Online (Sandbox Code Playgroud)
这可能需要在C++端进行一些重写以接受仿函数(或者只是块,如果它更简单)而不是函数指针.
由于块创建了闭包,因此它们对于这种作品非常方便.
Blocks是C,C++和Objective-C的Apple扩展.在这里查看更多相关信息.
使用Objective-C运行时访问选择器的函数指针.这更加繁琐,需要您跟踪三个变量(调用方法的对象,要使用的选择器和方法实现),但即使在不能使用Objective-C的情况下它也能正常工作句法.
Objective-C方法实现是具有此签名的函数指针:
typedef void (*IMP)(id self, SEL _cmd, ...);
Run Code Online (Sandbox Code Playgroud)
哪里self是你所期望,_cmd是导致该方法调用选择(该_cmd变量是在所有的Objective-C的方法,实际可用的,试试吧),其余的被认为是可变参数.您需要将IMP变量转换为正确的函数签名,因为可变参数C函数的调用约定并不总是与Objective-C方法调用的调用约定相匹配(Objective-C方法调用是编译器的标准函数调用约定,可能无论是cdecl或AMD64调用约定,和一个可变调用约定并不总是相同).A reinterpret_cast将能够做到这一点.
这里是我为相似意图编写的一些代码.它使用C++ 11可变参数模板来帮助获取正确的函数签名.
#include <objc/runtime.h>
template<typename TReturnType, typename... TArguments>
auto GetInstanceMethodPointer(Class class, SEL selector) -> TReturnType (*)(id, SEL, TArguments...)
{
Method m = class_getInstanceMethod(class, selector);
IMP imp = method_getImplementation(m);
return reinterpret_cast<TReturnType (*)(id, SEL, TArguments...)>(imp);
}
int main()
{
MyClass* instance = [[MyClass alloc] init];
auto foo = GetInstanceMethodPointer<void>(
[MyClass class],
@selector(my_callback));
// foo is a void (*)(id, SEL) function pointer
foo(instance, @selector(my_callback));
}
Run Code Online (Sandbox Code Playgroud)
nil在使用函数调用之前,请注意不要使用实例,因为nil检查是由Objective-C运行时处理的.在这种情况下,我们绕过它.
SEL使用-[NSObject performSelector:]进行回调.基本上是Objective-C运行时解决方案的更简单版本.
void setup_callback(id object, SEL selector)
{
// do stuff
// to execute the callback:
// [object performSelector:selector];
}
int main()
{
MyClass* instance = [[MyClass alloc] init];
setup_callback(instance, @selector(my_callback));
}
Run Code Online (Sandbox Code Playgroud)
我认为这个并不需要任何例子.创建一个接受对象类型作为第一个参数的函数,并在其上调用所需的方法.与SEL解决方案类似,您需要单独跟踪要调用的函数和调用它的对象.
| 归档时间: |
|
| 查看次数: |
7687 次 |
| 最近记录: |