假设您创建了一个main()
来处理您向学生询问的练习。
每个学生都应该使用相同的API编写自己的函数。将创建一个文件,包含所有函数和主函数。
让我们说:int studentname(int a, int b)
是功能模式。
我处理它的一种方法是使用指向函数int (*func[MAX])()
的向量。但是你需要逐个完成向量func[0]=studentname;
。
我想知道,有某种方法可以通过某种方式调用某个函数吗?
类似于:int student1(int a , int b)
,student2()
等
在main
{@ 1}}我们可以调用sscanf(funcname,"student%d",i); funcname();
。
int studentname(int a, int b, char *fname)
{
strcpy(fname, "studentname");
任何有创意的人都会做! :)
谢谢! 贝乔
PS。我尝试了一个函数向量,但C不允许我! :)
int func[2]()={{;},{;}};
这样我就可以给每个学生一个号码,然后瞧...但是没办法。这很有趣。
编辑:我正在使用linux。
编辑2:谢谢!我接受了一个帮助我的答案,但我还记录了一个完整的例子作为答案。
答案 0 :(得分:2)
可能有点过于复杂,但是自发的想法:
作为替代方案:
还有另一个想法:
extern "C"
嵌入学生的代码。根据实施情况,这可能看起来有点混乱和过于复杂。使用dlopen()
和dlsym()
的方法示例(每个库是否只有一个函数或全部 - 无关紧要):
void *pluginlib = dlopen("student1.so", RTLD_NOW); // RTLD_NOW will load the file right away
if (!pluginlib)
; // failed to load
studentproc func = (studentproc)dlsym(pluginlib, "student1"); // this loads the function called "student1"
if (!func)
; // failed to resolve
func("hello world!"); // call the lib
dlclose(pluginlib); // unloads the dll (this will make all further calls invalid)
答案 1 :(得分:2)
与@ Jamey-Sharp提出的相似:
.c
文件,其中包含给定名称/签名的入口功能.c
编译成一个共享库,由学生名称命名,或者给出任何唯一名称。使用make
或简单脚本可以轻松实现此步骤。.so
个文件,并使用dlopen()
和dlsym()
来获取入口点函数。编辑:这是一个有效的概念证明(以及每个学生可以使用相同名称的入口点函数的证据)。
这是student1.c
:
#include <stdio.h>
void student_task()
{
printf("Hello, I'm Student #1\n");
}
这是student2.c
:
#include <stdio.h>
void student_task()
{
printf("Hello, I'm Student #2\n");
}
这是主程序,tester.c
:
#include <stdio.h>
#include <dlfcn.h>
/* NOTE: Error handling intentionally skipped for brevity!
* It's not a production code!
*/
/* Type of the entry point function implemented by students */
typedef void (*entry_point_t)(void);
/* For each student we have to store... */
typedef struct student_lib_tag {
/* .. pointer to the entry point function, */
entry_point_t entry;
/* and a library handle, so we can play nice and close it eventually */
void* library_handle;
} student_solution_t;
void load(const char* lib_name, student_solution_t* solution)
{
/* Again - all error handling skipped, I only want to show the idea! */
/* Open the library. RTLD_LOCAL is quite important, it keeps the libs separated */
solution->library_handle = dlopen(lib_name, RTLD_NOW | RTLD_LOCAL);
/* Now we ask for 'student_task' function. Every student uses the same name.
* strange void** is needed for C99, see dlsym() manual.
*/
*(void**) (&solution->entry) = dlsym(solution->library_handle, "student_task");
/* We have to keep the library open */
}
int main()
{
/* Two entries hardcoded - you need some code here that would scan
* the directory for .so files, allocate array dynamically and load
* them all.
*/
student_solution_t solutions[2];
/* Load both solutions */
load("./student1.so", &solutions[0]);
load("./student2.so", &solutions[1]);
/* Now we can call them both, despite the same name of the entry point function! */
(solutions[0].entry)();
(solutions[1].entry)();
/* Eventually it's safe to close the libs */
dlclose(solutions[0].library_handle);
dlclose(solutions[1].library_handle);
return 0;
}
让我们编译所有:
czajnik@czajnik:~/test$ gcc -shared -fPIC student1.c -o student1.so -Wall
czajnik@czajnik:~/test$ gcc -shared -fPIC student2.c -o student2.so -Wall
czajnik@czajnik:~/test$ gcc tester.c -g -O0 -o tester -ldl -Wall
看到它有效:
czajnik@czajnik:~/test$ ./tester
Hello, I'm Student #1
Hello, I'm Student #2
答案 2 :(得分:1)
我采取不同的方法:
main
再写一个源文件。main.c
与student1.c
关联,然后将main.c
与student2.c
关联,依此类推。您可以在makefile或shell脚本中使用通配符来自动执行此操作。那就是说,至少在类Unix操作系统上,你可以做你所要求的。
dlopen(NULL)
来处理主程序中的符号。dlsym
。将结果指针强制转换为正确类型的函数指针,然后调用它。答案 3 :(得分:1)
这是一个丑陋的预处理程序黑客:
#Makefile
FILE_NAME=student
${FILE_NAME}: main.c
cc -Wall -DFILE_NAME=\"${FILE_NAME}.c\" -o $@ main.c -lm
老师的main.c:
#include <math.h>
#include <stdio.h>
#include FILE_NAME
char *my_name(void);
double my_sin(double val);
int main(void)
{
double dd;
dd = my_sin(3.1415923563);
printf("%s: %f\n", my_name(), dd);
return 0;
}
学生的.c文件:
#include <math.h>
char * my_name(void);
double my_sin(double val);
char * my_name(void)
{
return "Wildplasser-1.0";
}
double my_sin(double val)
{
return sin (val);
}
诀窍在于我是否包含了学生的.c文件。
为避免这种情况,您还可以使用不同的make行,例如:
cc -Wall -o $@ ${FILE_NAME}.c main.c -lm
(并删除丑陋的#include FILENAME
当然)
答案 4 :(得分:1)
谢谢大家。我接受了一个答案,给了我解决问题的灵感。在这里,只是为了记录它,是我的完整解决方案:
文件shamain.c
/* Uses shared library shalib.so
* Compile with:
* gcc shamain.c -o shamain -ldl -Wall
*/
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main(void)
{
void *libstud;
int (*student[2])(int, int);
char fname[32];
int i,r;
libstud = dlopen("./shalib.so", RTLD_NOW);
if (!libstud)
{
fprintf(stderr, "error: %s\n", dlerror());
exit(EXIT_FAILURE);
}
dlerror(); /* Clear any existing error */
for(i=0; i<2; i++)
{
sprintf(fname, "func%d", i);
*(void **) (&student[i]) = dlsym(libstud, fname); /* c99 crap */
//student[i] = (int (*)(int, int)) dlsym(libstud, fname); /* c89 format */
}
for(i=0; i<2; i++)
{
r=student[i](i, i);
printf("i=%d,r=%d\n", i, r);
}
return 0;
}
文件shalib.c
/* Shared library.
* Compile with:
* gcc -shared -fPIC shalib.c -o shalib.so -Wall
*/
#include <stdio.h>
int func0(int one, int jadv)
{
printf("%d = Smith\n", one);
return 0;
}
int func1(int one, int jadv)
{
printf("%d = John\n", one);
return 0;
}
答案 5 :(得分:0)
我使用共享库已经有一段时间了,但我觉得你可以从DLL / shlib中提取命名函数。你能创建一个包含所有实现的DLL /共享库,然后从主要的名称访问它们吗?
答案 6 :(得分:0)
根据@ william-morris的建议,您可能很幸运使用dlsym()
来动态查找函数。 (dlsym()
可能是也可能不是您在特定平台上使用的库调用。)