类似于@Jamey-Sharp 提出的建议:
- 要求每个学生提供
.c
具有给定姓名/签名的输入功能的文件
- 将每个文件编译
.c
成一个共享库,以学生姓名命名,或赋予任何唯一名称。此步骤可以使用make
简单的脚本轻松自动化。
- 制作一个简单的主机应用程序,它枚举
.so
给定目录中的所有文件,并使用dlopen()
和dlsym()
访问入口点函数。
- 现在您可以简单地调用每个学生的实现。
BTW,插件通常是这样实现的,不是吗?
编辑:这是一个工作概念证明(以及一个证明,每个学生都可以使用相同名称的入口点函数)。
这是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