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.
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());
}
}