我在其中一个C谜题中看到了这个问题! 这真的有可能吗?
如何将函数命名为字符串,如何调用函数? 是否可以使用scanf读取的字符串直接用于调用 一个功能?
我已经想过if(strcmp(str,“string”))然后调用函数。
但还有其他方法吗?
答案 0 :(得分:11)
既然没有提到什么是函数,也没有提及它的参数,我会想象它是这样的:
typedef void (*foo)(); struct puzzleFoo{ char *function_name; foo *fn; };
使用字符串参数
基于结构创建查找表struct puzzleFoo *Lookup(const char *function_name);
然后遍历查找puzzleFoo
的{{1}} e的数组/列表,并执行名为function_nam
的函数指针。
答案 1 :(得分:10)
使用POSIX.1-2001,您应该使用dlopen() and dlsym()。在Windows上使用GetModuleHandleEx()和GetProcAddress()。
以下是从手册中逐字逐句加载数学库中名为“cos”的函数并确定2.0的余弦的示例:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int
main(int argc, char **argv)
{
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen("libm.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
dlerror(); /* Clear any existing error */
/* Writing: cosine = (double (*)(double)) dlsym(handle, "cos");
would seem more natural, but the C99 standard leaves
casting from "void *" to a function pointer undefined.
The assignment used below is the POSIX.1-2003 (Technical
Corrigendum 1) workaround; see the Rationale for the
POSIX specification of dlsym(). */
*(void **) (&cosine) = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(EXIT_FAILURE);
}
printf("%f\n", (*cosine)(2.0));
dlclose(handle);
exit(EXIT_SUCCESS);
}
答案 2 :(得分:3)
你可能偷偷摸摸:
if (strcmp (fn, "function1") == 0) function1();
if (strcmp (fn, "function2") == 0) function2();
if (strcmp (fn, "function3") == 0) function3();
或者您可以使用dlopen
和dlsym
(或等效的),具体取决于您的执行环境,但这些不是标准C,因此可能不是一个选项。
除了可执行文件或设计可怕的宏(这很可能归结为上面显示的if
语句的集合或函数)之外,这就是我所拥有的非常可靠的东西。某种指针数组。)
答案 3 :(得分:3)
如果该功能在共享库中可用,您可以在运行时加载共享库并访问符号表,该表可以转换为函数名和指针。至于确保函数调用签名是正确的,你可以自己做。
VxWorks为其内置shell执行此操作。
答案 4 :(得分:3)
是的,有时候。
在Linux下,您可以使用dlopen()
打开包含所需功能的共享库,甚至可以访问当前可执行文件并使用dlsym()
在Windows上,您通常会分别拨打LoadLibrary()
和GetProcAddress()
。
如果相关库的符号表已被删除,或者在某些情况下,如果这些方法是静态/私有的,那么您将无法使用此方法访问它们。
另外,不要忘记,如果你的库是用C ++编写的,那么你可能不得不应对名称修改。您需要了解编译器使用的修改方法。
答案 5 :(得分:2)
取决于你想要打电话的功能。
如果这是来自DLL或其他类型的导出二进制文件的函数 - 当然你可以
这有一个普通的API
如果此函数未导出并且是以可执行文件编译的 - 当然不是,因为func名称等信息会被截断。
答案 6 :(得分:1)
我把它写在了我的头顶 - 不能保证它甚至会编译,但它可能非常接近。足以接受采访。
#include <stdio.h>
#include <unistd.h>
char *program = "#include<stdio.h>\
\
void Func1() { printf("hi\n"); }\
void Func2() { printf("hello\n"); }\
void Func3() { printf("hey\n"); }\
main() {\
";
char *program1 = "}\n";
static in ContainsFunction(char *func)
{
char *match = strstr(func, program);
if (!match || match - program < 5)
return 0;
int len = strlen(func);
return strcmp(match-5, program) == 0 && match[len + 1] == '(' && isalnum(func[len-1]);
}
static void Compile(char *prog)
{
pid_t pid = fork();
if (pid == 0) {
execl("/usr/bin/gcc", "gcc", prog, (char *)0);
}
else if (pid < 0) { printf("fork fail\n"); }
else {
pid_t ws = wait();
}
}
static void Execute(char *prog)
{
pid_t pid = fork();
if (pid == 0) {
execl(prog, prog, (char *)0);
}
else if (pid < 0) { printf("fork fail\n"); }
else {
pid_t ws = wait();
}
}
static void CallFunction(char *funcname)
{
FILE *fp = fopen("foo.c", "w");
fputs(program, fp);
fprintf(fp, "\t%s();\n", funcname);
fputs(fp, program1);
fclose(fp);
Compile("foo.c");
Execute("a.out");
}
int main()
{
char funcname[8192]; /* too small, fail */
puts("Who ya gonna call?");
gets(funcname);
if (ContainsFunction(funcname)) { CallFunction(funcname)); }
else { printf("fail - no function %s\n", funcname); }
}