몇 가지 옵션이 있습니다.
사용하여 블록
당신은 당신의 콜백 작업을 전달하기 위해 블록을 사용할 수 있습니다. 콜백 "함수"에 매개 변수를 전달하지 않고도 코드를 호출 할 수 있으므로 가장 간단한 솔루션 일 것입니다. 블록은 C와 Clang의 모든 상위 집합에서 작동하며 Clang ++는 블록과 람다간에 암시 적 캐스트를 허용합니다. 대신 함수 포인터의 펑 (또는 블록이 간단 경우)을 허용하도록 C++ 끝에 약간의 재 작업이 필요할 수 있습니다
#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];
});
}
.
블록이 클로저를 생성하기 때문에 이러한 종류의 작업에 매우 편리합니다.
블록은 C, C++ 및 Objective-C에 대한 Apple 확장 프로그램입니다. 그들에 대해 더 자세히보기 here.
당신이 당신의 선택의 함수 포인터를 액세스 할 수
사용 목적-C 런타임을 호출 할 메서드에 함수 포인터를 획득하기 위해 오브젝티브 C 런타임을 사용합니다. 이것은 더 지루하고 세 변수 (메서드를 호출 할 개체, 사용할 선택기 및 메서드 구현)를 추적해야하지만 실제로 Objective-C를 사용할 수없는 경우에도 작동합니다 통사론.
목표 - C 메소드 구현이 서명 함수 포인터 : self
당신이 기대하는 것입니다
typedef void (*IMP)(id self, SEL _cmd, ...);
이 _cmd
이 메서드 호출을 발생하는 선택입니다합니다 (_cmd
변수는 모두 실제로 볼 수 있습니다 Objective-C 방법, 시도해보십시오) 나머지는 가변적 인 것으로 간주됩니다. IMP
변수를 적절한 함수 시그니처에 캐스팅해야합니다. 가변 C 함수의 호출 규칙이 Objective-C 메서드 호출의 호출 규칙과 항상 일치하지 않기 때문입니다. Objective-C 메서드 호출은 사용자의 표준 함수 호출 규칙입니다. 컴파일러, 아마도 cdecl
또는 amd64 호출 규칙이며 가변적 호출 규칙은 이 아니며 항상 같은 것입니다. reinterpret_cast
이이를 수행 할 수 있습니다.
다음은 비슷한 의도로 작성된 코드입니다. 적절한 함수 서명을 얻는 데 도움이되는 C++ 11 가변 템플릿을 사용합니다. nil
검사가 목표 - C 런타임에 의해 처리되기 때문에
#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));
}
또한, 인스턴스는 함수 호출을 사용하기 전에하지 nil
입니다주의해야합니다. 이 경우 우회합니다. 객체의
보관할 트랙과 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));
}
++ 기능
는 C 내부 전화를 포장 나는이 사람이 정말 어떤 예제를 필요로하지 않는다 생각합니다. 첫 번째 매개 변수로 객체 유형을 허용하고 원하는 메소드를 호출하는 함수를 만듭니다. SEL
솔루션과 마찬가지로 호출 할 함수와 호출 할 개체를 개별적으로 추적해야합니다.
구현을받을 필요가 없습니다. – user102008
구현 대신 항상'objc_msgSend'를 사용할 수 있습니다. 이 경우 메서드 포인터 대신 선택기를 사용합니다. – zneak
아니요. IMP를 사용하면 선택기를 가지고 있어야합니다. 이제는 IMP를 얻을 필요가 없다는 점을 제외하면 동일합니다. – user102008