3

Is it possible to call a function by name in Objective C? For instance, if I know the name of a function ("foo"), is there any way I can get the pointer to the function using that name and call it? I stumbled across a similar question for python here and it seems it is possible there. I want to take the name of a function as input from the user and call the function. This function does not have to take any arguments.

Community
  • 1
  • 1
341008
  • 9,862
  • 11
  • 52
  • 84
  • 1
    Being a bit pedantic, a function in Objective-C is exactly the same as a function in C, so the answer is "no". What you're probably interested in is sending messages by name. – JeremyP Feb 10 '11 at 08:49
  • Being a complete noob to Obj-C, I am still to figure out all the messaging stuff. Thanks for the clarification. +1 – 341008 Feb 10 '11 at 09:02
  • @JeremyP Why is the answer "no" if it is possible via `dlsym()` if the corresponding symbol hasn’t been stripped (it generally isn’t)? –  Feb 10 '11 at 09:09
  • @Bavarious: dlsym is not part of C99. As you pointed out, it won't work for functions not exported by a dylib and it won't work for stripped exes. Distribution binaries often are stripped. – JeremyP Feb 10 '11 at 09:18

1 Answers1

8

For Objective-C methods, you can use performSelector… or NSInvocation, e.g.

NSString *methodName = @"doSomething";
[someObj performSelector:NSSelectorFromString(methodName)];

For C functions in dynamic libraries, you can use dlsym(), e.g.

void *dlhandle = dlopen("libsomething.dylib", RTLD_LOCAL);
void (*function)(void) = dlsym(dlhandle, "doSomething");
if (function) {
    function();
}

For C functions that were statically linked, not in general. If the corresponding symbol hasn’t been stripped from the binary, you can use dlsym(), e.g.

void (*function)(void) = dlsym(RTLD_SELF, "doSomething");
if (function) {
    function();
}

Update: ThomasW wrote a comment pointing to a related question, with an answer by dreamlax which, in turn, contains a link to the POSIX page about dlsym. In that answer, dreamlax notes the following with regard to converting a value returned by dlsym() to a function pointer variable:

The C standard does not actually define behaviour for converting to and from function pointers. Explanations vary as to why; the most common being that not all architectures implement function pointers as simple pointers to data. On some architectures, functions may reside in an entirely different segment of memory that is unaddressable using a pointer to void.

With this in mind, the calls above to dlsym() and the desired function can be made more portable as follows:

void (*function)(void);
*(void **)(&function) = dlsym(dlhandle, "doSomething");
if (function) {
    (*function)();
}
Community
  • 1
  • 1
  • Does `void (*function)() = dlsym(RTLD_SELF, "doSomething");` work on iOS? – 341008 Feb 18 '11 at 14:12
  • @341008 see this answer for correct formatting http://stackoverflow.com/a/5213272/211292 – ThomasW Dec 13 '11 at 09:32
  • Note that you can also do this for other symbol references: `NSString **ADBannerContentSizeIdentifierPortraitPtr = dlsym(RTLD_SELF, "ADBannerContentSizeIdentifierPortrait");` – ThomasW Mar 26 '13 at 05:47