通过用户输入的名称调用函数

341*_*008 3 objective-c

是否可以在Objective C中按名称调用函数?例如,如果我知道函数的名称("foo"),有什么办法可以使用该名称获取指向函数的指针并调用它?我在这里偶然发现了类似的python问题,似乎有可能存在.我想将一个函数的名称作为用户的输入并调用该函数.此函数不必采用任何参数.

小智 7

对于Objective-C方法,您可以使用performSelector…NSInvocation,例如

NSString *methodName = @"doSomething";
[someObj performSelector:NSSelectorFromString(methodName)];
Run Code Online (Sandbox Code Playgroud)

对于动态库中的C函数,您可以使用dlsym(),例如

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

对于静态链接的C函数,通常不是.如果没有从二进制文件中删除相应的符号,则可以使用dlsym(),例如

void (*function)(void) = dlsym(RTLD_SELF, "doSomething");
if (function) {
    function();
}
Run Code Online (Sandbox Code Playgroud)

更新: ThomasW写了一个评论指向一个相关的问题,由dreamlax回答,反过来,它包含一个指向POSIX页面dlsym的链接.在该答案中,dreamlax注意到以下关于将返回的值转换dlsym()为函数指针变量:

C标准实际上并没有定义转换为函数指针和从函数指针转换的行为.解释因为原因而有所不同; 最常见的是并非所有体系结构都将函数指针实现为数据的简单指针.在某些体系结构中,函数可能驻留在完全不同的内存段中,使用指向void的指针是无法寻址的.

考虑到这一点,上面的调用dlsym()和所需的功能可以更加便携,如下所示:

void (*function)(void);
*(void **)(&function) = dlsym(dlhandle, "doSomething");
if (function) {
    (*function)();
}
Run Code Online (Sandbox Code Playgroud)