@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