Anda memiliki dua opsi, yang dapat Anda pilih:
Opsi 1:ekspor semua simbol dari executable Anda. Ini adalah opsi sederhana, saat membuat executable, tambahkan flag -Wl,--export-dynamic
. Ini akan membuat semua fungsi tersedia untuk panggilan perpustakaan.
Opsi 2:buat file simbol ekspor dengan daftar fungsi, dan gunakan -Wl,--dynamic-list=exported.txt
. Ini membutuhkan beberapa pemeliharaan, tetapi lebih akurat.
Untuk mendemonstrasikan:pustaka sederhana yang dapat dieksekusi dan dimuat secara dinamis.
#include <stdio.h>
#include <dlfcn.h>
void exported_callback() /*< Function we want to export */
{
printf("Hello from callback!\n");
}
void unexported_callback() /*< Function we don't want to export */
{
printf("Hello from unexported callback!\n");
}
typedef void (*lib_func)();
int call_library()
{
void *handle = NULL;
lib_func func = NULL;
handle = dlopen("./libprog.so", RTLD_NOW | RTLD_GLOBAL);
if (handle == NULL)
{
fprintf(stderr, "Unable to open lib: %s\n", dlerror());
return -1;
}
func = dlsym(handle, "library_function");
if (func == NULL) {
fprintf(stderr, "Unable to get symbol\n");
return -1;
}
func();
return 0;
}
int main(int argc, const char *argv[])
{
printf("Hello from main!\n");
call_library();
return 0;
}
Kode pustaka (lib.c):
#include <stdio.h>
int exported_callback();
int library_function()
{
printf("Hello from library!\n");
exported_callback();
/* unexported_callback(); */ /*< This one will not be exported in the second case */
return 0;
}
Jadi, pertama bangun perpustakaan (langkah ini tidak berbeda):
gcc -shared -fPIC lib.c -o libprog.so
Sekarang buat yang dapat dieksekusi dengan semua simbol yang diekspor:
gcc -Wl,--export-dynamic main.c -o prog.exe -ldl
Jalankan contoh:
$ ./prog.exe
Hello from main!
Hello from library!
Hello from callback!
Simbol yang diekspor:
$ objdump -e prog.exe -T | grep callback
00000000004009f4 g DF .text 0000000000000015 Base exported_callback
0000000000400a09 g DF .text 0000000000000015 Base unexported_callback
Sekarang dengan daftar yang diekspor (exported.txt
):
{
extern "C"
{
exported_callback;
};
};
Bangun &periksa simbol yang terlihat:
$ gcc -Wl,--dynamic-list=./exported.txt main.c -o prog.exe -ldl
$ objdump -e prog.exe -T | grep callback
0000000000400774 g DF .text 0000000000000015 Base exported_callback
Anda perlu membuat fungsi register di .so agar executable dapat memberikan penunjuk fungsi ke .so Anda untuk digunakan nanti.
Seperti ini:
void in_main_func () {
// this is the function that need to be called from a .so
}
void (*register_function)(void(*)());
void *handle = dlopen("libmylib.so");
register_function = dlsym(handle, "register_function");
register_function(in_main_func);
register_function perlu menyimpan pointer fungsi dalam variabel di .so di mana fungsi lain di .so dapat menemukannya.
Mylib.c Anda perlu terlihat seperti ini:
void (*callback)() = NULL;
void register_function( void (*in_main_func)())
{
callback = in_main_func();
}
void function_needing_callback()
{
callback();
}
-
Letakkan prototipe fungsi utama Anda dalam file .h dan sertakan dalam kode pustaka utama dan dinamis Anda.
-
Dengan GCC, cukup kompilasi program utama Anda dengan
-rdynamic
bendera. -
Setelah dimuat, pustaka Anda akan dapat memanggil fungsi dari program utama.
Sedikit penjelasan lebih lanjut adalah setelah dikompilasi, pustaka dinamis Anda akan memiliki simbol yang tidak terdefinisi di dalamnya untuk fungsi yang ada di kode utama. Setelah aplikasi utama Anda memuat pustaka, simbol akan diselesaikan oleh tabel simbol program utama. Saya telah menggunakan pola di atas berkali-kali dan itu berfungsi dengan sangat baik.