Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
386 views
in Technique[技术] by (71.8m points)

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

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 main.c (executable) which contains:

void inmain_function(void*);
dlopen("libmy.so");

In the my.c (the code for the libmy.so) I want to call inmain_function:

inmain_function(NULL);

How can the shared library call inmain_function regardless the fact inmain_function is defined in the main program.

Note: I want to call a symbol in main.c from my.c not vice versa which is the common usage.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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 <stdio.h>
#include <dlfcn.h>

void exported_callback() /*< Function we want to export */
{
    printf("Hello from callback!
");
}

void unexported_callback() /*< Function we don't want to export */
{
    printf("Hello from unexported callback!
");
}

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
", dlerror());
       return -1;
   }
   func = dlsym(handle, "library_function");

   if (func == NULL) {
       fprintf(stderr, "Unable to get symbol
");
      return -1;
   }

   func();
   return 0;
}

int main(int argc, const char *argv[])
{
    printf("Hello from main!
");
    call_library();
    return 0;
}

Library code (lib.c):

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

int library_function()
{
    printf("Hello from library!
");
    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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...