How to get a function pointer from a shared library (.so)?

Manda Rajo 141 Reputation points
2022-06-12T19:57:15.74+00:00

Hi, how to fix that famous dlerror? Because calling getFunctionPointer(lib, "set") causes that error, which is same as dlsym(lib, "set") which returns nullptr. Where lib is the handle to the library which is a .so file instead of a .dll file. Note that I could successfully open the library (.so) with dlopen() because the line printf("Library is initialized\n"); in the screenshot is called, and it outputs Library is initialized on the console.

https://github.com/dlfcn-win32/dlfcn-win32
The above is the GitHub link where I downloaded dlfcn.c and dlfcn.h and only put those 2 files in my Visual Studio 2015 project. I don't know if it causes a problem too because I ignored the CMakeLists.txt from the original GitHub project. Should I copy the complex settings from that to the CMakeLists.txt of my project?

When I press F5 to run the code then this error shows:
Could not get function pointer for "set":
Error: "set": The specified procedure could not be found.

210587-dlsym.jpg

The steps when F5 is pressed with runCmd() which runs a command:

   // Create the object files (.o)  
   string objs = "";  
   for (int i = 0; i < names.size(); i++) {  
       ...  
       string f = isSharedLibrary ? "-fPIC" : "";  
       runCmd("gcc -Wall -c " + f + " " + MACRO_FILE(names[i], ".cpp") + " -o \""+o+"\"", printOutput);  
   }  
   // Create the shared library (.so)  
   runCmd("gcc -shared " + objs + " -o " + MACRO_FILE(libraryName, ".so"), printOutput);  

Referenced from https://renenyffenegger.ch/notes/development/languages/C-C-plus-plus/GCC/create-libraries/index

   #define MACRO_FILE_NOQUOTATIONMARKS(name, extension) (dir + "/" + name + extension)  
   #define MACRO_FILE(name, extension) (string("\"") + MACRO_FILE_NOQUOTATIONMARKS(name, extension) + "\"")  
     
   void *getFunctionPointer(void *lib, const char *funcName) {  
       // Get the function pointer to the function  
       void *fptr = dlsym(lib, funcName);  
       if (!fptr) {  
         string s = string_sprintf("Could not get function pointer for \"%s\":\nError: %s\n\n", funcName, dlerror());  
         EMC_ERROR(s.c_str());  
         return NULL;  
       }  
       return fptr;  
   }  
   void EmclProject::run()  
   {  
       string dir = binPath(this->_emc_projectName) + "/emcl";  
       string libraryName = "_emcl_testlib";  
       compile(dir, libraryName);  
     
       {  
           // Declare the function pointers:  
   #pragma GCC diagnostic push  
   #pragma GCC diagnostic ignored "-Wunused-but-set-variable"  
           typedef void (*fptr_null)(int);  
   #pragma GCC diagnostic pop  
           typedef void (*fptr_set)(int);  
           typedef void (*fptr_add)(int);  
           typedef int  (*fptr_get)();  
     
           // Open the dynamic library  
           string file = MACRO_FILE_NOQUOTATIONMARKS(libraryName, ".so");  
           void *lib = dlopen(file.c_str(), RTLD_LAZY | RTLD_GLOBAL);  
           if (!lib) {  
               // Apparently, the library could not be opened  
               EMC_ERROR((string("Could not open ")+file+"\n").c_str());  
               exit(1);  
           }  
     
           // Get the pointers to the functions within the library:  
         //fptr_null null = reinterpret_cast<fptr_null>(getFunctionPointer(handle, "doesNotExist")); // Function doesNotExist does not exist, demonstrate calling dlerror()  
           fptr_set set = reinterpret_cast<fptr_set> (getFunctionPointer(lib, "set"));  
           fptr_add add = reinterpret_cast<fptr_add> (getFunctionPointer(lib, "add"));  
           fptr_get get = reinterpret_cast<fptr_get> (getFunctionPointer(lib, "get"));  
     
           // Call the function via the function pointer  
           set(10);  
           add(5);  
           printf("Result: %d\n", get());  
       }  
   }  
Developer technologies | C++
{count} votes

2 answers

Sort by: Most helpful
  1. Minxin Yu 13,501 Reputation points Microsoft External Staff
    2022-06-13T07:32:48.577+00:00

    Hi,
    For your reference: Access pointer from shared library in C

    void ** myptr = (void**)dlsym(lib, "myptr");
    void (fcn)() = (void ()()) (*myptr);

    Best regards,

    Minxin Yu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

  2. Manda Rajo 141 Reputation points
    2022-06-13T08:14:38.62+00:00

    I insert extern "C" before the functions declarations and it works. But I should not do it to all the functions, I must only do it to specific functions that should be exported from the library, because inserting extern "C" causes a limitation on the function name (C style rather than C++ style).

       // Transpiled C++ code from emc-language.  
       #include <stdlib.h>  
       #include <string>  
       using std::string; using std::to_string;  
         
       int g_x;  
       extern "C" void set(int x)  
       {  
           g_x = x;  
       }  
       extern "C" void add(int x)  
       {  
           g_x += x;  
       }  
       extern "C" int get()  
       {  
           return g_x;  
       }  
       void __attribute__ ((constructor)) initLibrary(void)  
       {  
           printf("Library is initialized\n");  
       }  
       void __attribute__ ((destructor)) cleanUpLibrary(void)  
       {  
           printf("Library is exited\n");  
       }  
    

    How I call the functions:

       // Call the function via the function pointer  
       set(10);  
       add(5);  
       printf("Result: %d\n", get());  
    

    Output:
    Library is initialized
    Result: 15

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.