0

I'm developing an app that needs to perform some swizzling. I'm swizzling a method -(void)m1:(CMAcceleration)a; with another one that I provide.

-(void)newM(id self, SEL _cmd, ...){
va_list args;
va_start(args, _cmd);
//...
NSInteger returnValue=((NSInteger(*)(id,SEL,...))origImp)(self,_cmd,args);
va_end(args);
}

To swizzle it I use:

origImp=method_setImplementation(method, newImp);

I then call it normally like [ClassInstance m1:a]; The thing is, args seems to be filled with garbage when I expected a structure like {name=type...} as described in here. I need to pass the arguments to the original implementation after doing some operation like NSLog.

Searching the Internet it seems this is a Simulator problem related but I'm not sure and I have no access to a device to confirm this.

Am I doing something wrong or is there a way to fix this?

Leonardo Marques
  • 3,721
  • 7
  • 36
  • 50
  • What do you "args seems to be filled with garbage"? Show the code you used to determine that. What do you mean you "expected a structure like `{name=type...}`"? Show code for how you expected to be able to use the arguments, how you expected it to behave, and how it's actually behaving. Also show an example call of the method. – Ken Thomases Dec 13 '15 at 21:18
  • @KenThomases I edited it, hope it helps – Leonardo Marques Dec 13 '15 at 22:42

1 Answers1

1

You are doing it very wrong.

The method signature should match i.e. -(void)newM:(CMAcceleration)a;

and

Method method = class_getInstanceMethod([SomeClass class],@selector(newM:));
IMP newImp = method_getImplementation(method);
origImp=method_setImplementation(method, newImp);

A different way is make C function

void newM(id self, SEL _cmd, CMAcceleration a) {

}

origImp=method_setImplementation(method, (IMP)newM);
Bryan Chen
  • 45,816
  • 18
  • 112
  • 143
  • Isn't there a more generic way to do it? I'd like my newM method implementation to be swizzled into a wide variety of methods. – Leonardo Marques Dec 13 '15 at 22:23
  • No if those methods have different signatures. Unless you want to do some low level (assembly) work to create a function that _correctly_ accept any number of arguments. (You need to respect to ARC modifiers to avoid crash) – Bryan Chen Dec 13 '15 at 22:28
  • What so you mean with "correctly accept any number of arguments"? Isn't that what variable argument functions are? – Leonardo Marques Dec 13 '15 at 22:43
  • 1
    @LeonardoMarques No. It is not. Depends on the arch and platform, `void m(...)` and `void m(double)` and `void(id)` may have different calling convention. Arguments may be passed by stack, by register, by fp register, you have to handle all different cases. It is impossible to do this without assembly code. – Bryan Chen Dec 13 '15 at 22:49
  • Don't all methods get the objc_msgSend the same way? Maybe this could be a way around it? – Leonardo Marques Dec 14 '15 at 08:03
  • 1
    @LeonardoMarques Yes and No. You need to cast `objc_msgSend` to receive correct type first (compile does it automatically). Read this answer for more info: http://stackoverflow.com/a/2573949/642626 – Bryan Chen Dec 14 '15 at 20:50