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