san*_*p22 6 c function-pointers
我有一个主要功能如下:
#include <stdio.h>
int main(int argc, char *argv[])
{
int i, sum = 0;
char *func_user = argv[1];
// execute func_user function
return 0;
}
void foo1(void)
{
printf("I'm foo1.");
}
void foo2(void)
{
printf("I'm foo2.");
}
void foo3(void)
{
printf("I'm foo3.");
}
Run Code Online (Sandbox Code Playgroud)
我希望用户将他的函数名称作为main的参数,我希望我的程序执行这个给定的函数.有没有办法做这个(比如使用反射)而不使用switch/case方法?
Som*_*ude 14
你不能直接这样做,因为C既没有内省也没有反思.您必须自己将名称(字符串)映射到(指向a)函数.
一种不常见的创建这种映射的方法是使用具有该信息的结构,然后对所有函数使用这些结构的数组.然后迭代数组以查找名称及其函数指针.
也许是这样的
struct name_function_map_struct
{
char *name; // Name of the function
void (*function)(void); // Pointer to the function
};
// Declare function prototypes
void foo1(void);
void foo2(void);
void foo3(void);
// Array mapping names to functions
const struct name_function_map_struct name_function_map[] = {
{ "foo1", &foo1 },
{ "foo2", &foo2 },
{ "foo3", &foo3 }
};
int main(int argc, char *argv[])
{
// Some error checking
if (argc < 2)
{
// Missing argument
return 1;
}
// Calculate the number of elements in the array
const size_t number_functions = sizeof name_function_map / sizeof name_function_map[0]
// Find the function pointer
for (size_t i = 0; i < number_functions; ++i)
{
if (strcmp(argv[1], name_function_map[i].name) == 0)
{
// Found the function, call it
name_function_map[i].function();
// No need to search any more, unless there are duplicates?
break;
}
}
}
// The definitions (implementations) of the functions, as before...
...
Run Code Online (Sandbox Code Playgroud)
是的,但你可能不希望这样做是因为你的目标(即避免switch陈述).从另外一个SO回答(通过编译gcc -std=c99 -Wall -rdynamic ds.c -o ds -ldl,假设文件名是ds.c)(请记住,你需要知道函数签名,即:返回类型加参数;提前).
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void hello ()
{
printf ("hello world\n");
}
int main (int argc, char **argv)
{
char *buf = "hello";
void *hndl = dlopen (NULL, RTLD_LAZY);
if (!hndl) { fprintf(stderr, "dlopen failed: %s\n", dlerror());
exit (EXIT_FAILURE); };
void (*fptr) (void) = dlsym (hndl, buf);
if (fptr != NULL)
fptr ();
else
fprintf(stderr, "dlsym %s failed: %s\n", buf, dlerror());
dlclose (hndl);
}
Run Code Online (Sandbox Code Playgroud)
你最好只创建一个专门提供函数/字符串映射的函数.我提供的例子只是为了证明你所要求的东西可以做到.只因为你可以,并不意味着你应该.
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void foo1(void);
void foo2(void);
void foo3(void);
int main (int argc, char **argv)
{
/* dlopen() self. */
void *hndl = dlopen (NULL, RTLD_LAZY);
if (!hndl) { fprintf(stderr, "dlopen failed: %s\n", dlerror());
exit (EXIT_FAILURE); };
/* Attempt to find symbols and call them. */
for (int i = 0; i < argc; i++) {
void (*fptr) (void) = dlsym(hndl, argv[i]);
if (fptr != NULL)
fptr();
else
fprintf(stderr, "dlsym %s failed: %s\n", argv[i], dlerror());
}
/* Cleanup. */
dlclose (hndl);
return 0;
}
void foo1()
{
printf("hello world\n");
}
void foo2()
{
printf("Mello world\n");
}
void foo3()
{
printf("Jello world\n");
}
Run Code Online (Sandbox Code Playgroud)
./ds foo1 foo2 foo3 foo1
dlsym ./ds failed: ./ds: undefined symbol: ./ds
hello world
Mello world
Jello world
hello world
Run Code Online (Sandbox Code Playgroud)