#include <stddef.h> #include <stdbool.h> #include <stdio.h> #include <dlfcn.h> bool init_library(void *hdl, void(*print_hello)(const char *)) { hdl = dlopen("./libHello.so", RTLD_LAZY); if (NULL == hdl) return false; print_hello = (void(*)(const char *)) dlsym(hdl, "print_hello"); if(NULL == print_hello) return false; return true; } int main() { void (*print_hello)(const char *); void *hdl; if(init_library(hdl, print_hello)) print_hello("Vasya"); else printf("Library was not loaded\n"); dlclose(hdl); return 0; } 

compile so gcc main.c -ldl -o exe eventually segmented error. even if you put printf ("1 \ n"); at the beginning of the main - anyway segmentation error.

hello.c code

 #include <stdio.h> #include "hello.h" void print_hello(const char *name) { printf("Hello, %s!\n", name); } 

hello.h code

 #ifndef __HELLO__ #define __HELLO__ void print_hello(const char *name); #endif 

Makefile for libHello.so

 libHello: hello.h hello.c gcc -shared hello.c -fPIC -o libHello.so 

the following code is executed without error

 #include <stddef.h> #include <stdbool.h> #include <stdio.h> #include <dlfcn.h> int main() { void *hdl; hdl = dlopen("./libHello.so", RTLD_LAZY); void (*print_hello)(const char *); print_hello = (void(*)(const char *)) dlsym(hdl, "print_hello"); print_hello("Vasya"); dlclose(hdl); return 0; } 

compile gcc main.c -ldl -o exe

    2 answers 2

    You are changing a local variable. Outside the function call, the print_hello pointer does not change. You can declare a separate type for a function pointer and pass the address of a variable.

     #include <stddef.h> #include <stdbool.h> #include <stdio.h> #include <dlfcn.h> typedef void(*hello_ptr)(const char *); bool init_library(void *hdl, hello_ptr* print_hello) { hdl = dlopen("./libHello.so", RTLD_LAZY); if (NULL == hdl) return false; // сохраняем адрес функции *print_hello = (hello_ptr) dlsym(hdl, "print_hello"); if(NULL == print_hello) return false; return true; } int main() { hello_ptr print_hello; void *hdl; if(init_library(hdl, &print_hello)) // передаем адрес, куда сохранять print_hello("Vasya"); else printf("Library was not loaded\n"); dlclose(hdl); return 0; } 
    • Thanks, hello Vasya printed. but now a new problem: Inconsistency detected by ld.so: dl-close.c: 762: _dl_close: Assertion `map-> l_init_called 'failed! - Bambaleila
    • one
      Exactly the same problem with the library handle - only the local variable changes, hdl in the main function does not change - Maxim Timakov

    If instead of bool return from init_library() what is really required of it - a pointer to an open lib (i.e., the result of dlopen() ), the code will be somewhat simpler.

    For example, you can rewrite it like this:

     #include <stddef.h> #include <stdio.h> #include <dlfcn.h> void * init_library(void **init_functon) { void *hdl = dlopen("./libHello.so", RTLD_LAZY); if (hdl) if (!(*init_function = dlsym(hdl, "print_hello"))) hdl = 0; return hdl; } int main() { void (*print_hello)(const char *); void *hdl = init_library((void **)&print_hello); if (hdl) { print_hello("Vasya"); dlclose(hdl); } return hdl ? 0 : printf("Library was not loaded\n") != 0; } 

    And note that you cannot call dbclose() , with a null pointer.

    And if you like "one-liners", then init_library() can be represented like this:

     void * init_library(void **print_hello) { void *hdl = dlopen("./libHello.so", RTLD_LAZY); return hdl && (*print_hello = dlsym(hdl, "print_hello")) ? hdl : 0; }