Skip to content

Instantly share code, notes, and snippets.

@OneSadCookie
Created November 22, 2014 01:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OneSadCookie/0413b4de4b25c2afd142 to your computer and use it in GitHub Desktop.
Save OneSadCookie/0413b4de4b25c2afd142 to your computer and use it in GitHub Desktop.
// c++ -g -std=c++11 -fobjc-arc -framework Foundation test.mm && ./a.out
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface X : NSObject
- (void)method1;
- (int)method2:(int)arg;
- (BOOL)method3:(BOOL)arg;
@end
@implementation X
- (void)method1
{
sleep(1);
}
- (int)method2:(int)arg
{
sleep(2);
return arg;
}
- (BOOL)method3:(BOOL)arg
{
return arg;
}
@end
struct probie_timer
{
probie_timer() : _start([NSDate timeIntervalSinceReferenceDate]) {}
~probie_timer() { NSLog(@"%f", [NSDate timeIntervalSinceReferenceDate] - _start); }
private:
NSTimeInterval _start;
};
template<class T>
void check_encode(char const *buf)
{
assert(strcmp(buf, @encode(T)) == 0);
}
template<unsigned i, class T>
void check_arg(Method m)
{
char buf[1024];
method_getArgumentType(m, i, buf, 1024);
check_encode<T>(buf);
}
template<class T>
void check_return(Method m)
{
char buf[1024];
method_getReturnType(m, buf, 1024);
check_encode<T>(buf);
}
template<unsigned i, class A, class... Args>
void check_args(Method m)
{
check_arg<i, A>(m);
check_args<i + 1, Args...>(m);
}
template<unsigned i>
void check_args(Method m)
{
assert(i == method_getNumberOfArguments(m));
}
template<class R, class... Args>
void check_method(Method m)
{
check_return<R>(m);
check_args<2, Args...>(m);
}
template<class C, class R, class... Args>
void probie(SEL s)
{
Method orig = class_getInstanceMethod([C class], s);
check_method<R, Args...>(orig);
IMP imp = method_getImplementation(orig);
auto block = [=](C *self, Args... args) -> R {
probie_timer t;
return ((R (*)(id, SEL, Args...))imp)(self, s, args...);
};
IMP new_imp = imp_implementationWithBlock(block);
method_setImplementation(orig, new_imp);
}
int main()
{
probie<X, void>(@selector(method1));
probie<X, int, int>(@selector(method2:));
X *x = [X new];
[x method1];
printf("%d\n", [x method2:3]);
// asserts:
probie<X, BOOL, int>(@selector(method3:));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment