How can a shared library (.so) call a function that is implemented in its loading program?

前端 未结 4 816
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-30 00:11

I have a shared library that I implemented and want the .so to call a function that\'s implemented in the main program which loads the library.

Let\'s say I have mai

4条回答
  •  -上瘾入骨i
    2020-11-30 00:31

    You have two options, from which you can choose:

    Option 1: export all symbols from your executable. This is simple option, just when building executable, add a flag -Wl,--export-dynamic. This would make all functions available to library calls.

    Option 2: create an export symbol file with list of functions, and use -Wl,--dynamic-list=exported.txt. This requires some maintenance, but more accurate.

    To demonstrate: simple executable and dynamically loaded library.

    #include 
    #include 
    
    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;
    }
    

    Library code (lib.c):

    #include 
    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;
    }
    

    So, first build the library (this step doesn't differ):

     gcc -shared -fPIC lib.c -o libprog.so
    

    Now build executable with all symbols exported:

     gcc -Wl,--export-dynamic main.c -o prog.exe -ldl
    

    Run example:

     $ ./prog.exe
     Hello from main!
     Hello from library!
     Hello from callback!
    

    Symbols exported:

     $ objdump -e prog.exe -T | grep callback
     00000000004009f4 g    DF .text  0000000000000015  Base        exported_callback
     0000000000400a09 g    DF .text  0000000000000015  Base        unexported_callback
    

    Now with the exported list (exported.txt):

    {
        extern "C"
        {
           exported_callback;
        };
    };
    

    Build & check visible symbols:

    $ 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
    

提交回复
热议问题