Cách sử dụng dlopen, dlsym để gọi đến hàm trong shared library(.so)

0

 


các chương trình được viết bằng c/c++ sau khi build ra và đưa đến người dùng không dưới dạng mã nguồn. vì vậy bỗng 1 ngày nào đó chúng ta muốn nâng cấp chương trình lên hoặc bổ sung thêm các hàm mới vào chương trình hiện tại sẽ rất khó khăn vì không có mã nguồn hoàn chỉnh.

để làm được điêu này chúng ta sẽ sử dụng Shared Library(.so) để tương tác với chương trình chính. code trong shared library(.so) sẽ là code mới mà chúng ta cần bổ sung, để làm dược điều này ngoài kiến thức cơ bản về c/c++ bạn cần phải am hiểu về mã máy(Assembly) thì mới có thể lắp ráp các hàm cần thiết để sử dụng dlopen và dlsym  gọi đến Shared library(.so) 
Triển khai 
đầu tiên sẽ tạo 1 file  main.c và lib.c với đoạn code dưới đây
trong hàm call_library sẽ dùng dlopen để load file callback.so mà chúng ta sẽ khởi tạo.
sau khi load xong file callback.so  chúng ta sẽ dùng hàm dlsym  để thực thi hàm library_function ở trong callback.so
trong hàm library_function  ở file callback.so sẽ gọi ngược lại hàm exported_callback trong file main.c tương ứng với chương trình của chúng ta đang chạy.

lib.c
#include <stdio.h>
int exported_callback();

int library_function()
{
    printf("bạn đã gọi đến game.so!\n");
    exported_callback();
    /* unexported_callback(); */ /*< This one will not be exported in the second case */
    return 0;
}

main.c
#include <stdio.h>
#include <dlfcn.h>

void exported_callback() /*< Function we want to export */
{
    printf("đây là hàm chính được gọi!\n");
}

void unexported_callback() /*< Function we don't want to export */
{
    printf("đây là hàm chúng ta không muốn callback!\n");
}

typedef void (*lib_func)();

int call_library()
{
   void     *handle  = NULL;
   lib_func  func    = NULL;
   handle = dlopen("./callback.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;
}
sau đó thực hiện 2 lệnh dưới để build ra file tương ứng
main.c = main
lib.c = callback.so
build main file :       gcc -Wl,--export-dynamic main.c -o main -ldl
build lib.so file :     gcc -shared -fPIC lib.c -o callback.so
kết quả : khi chạy chương trình main



Post a Comment

0Comments
Post a Comment (0)