niraami
niraami

Reputation: 657

Local dynamic library

Right off the bat, I want to say that I've never worked with dynamic libraries so It's possible that I don't even understand how they work properly.

I want to have a fully loaded code running and after some trigger (probably user interaction) I want to load a specific library and execute a function inside that library. Preferably close it afterwards. Essentially allowing me to change it and re-load it during run time.

This is the simple dynamic library (called dynlib.so located in the same directory as the main code):

int getInt(int arg_0)
{
  return (arg_0 + 7);
}

And this is the main program:

#include <iostream>
#include <dlfcn.h>

int main() {
  void *lib_handle = dlopen("./dynlib.so", RTLD_LAZY | RTLD_NOW);
  if (!lib_handle) {
    fprintf(stderr, "%s\n", dlerror());
    exit(EXIT_FAILURE);
  }

  typedef int (*func_ptr)(int);
  func_ptr func = (func_ptr)dlsym(lib_handle, "getInt");
  std::cout << func(13);

  dlclose(lib_handle);
}

I'm compiling it using: g++ -std=c++11 -ldl loadlibtest.cpp -o main.

The error I'm catching is ./libshared.so: file too short In my if (!lib_handle) {.

Upvotes: 1

Views: 224

Answers (2)

niraami
niraami

Reputation: 657

After some great replies I discovered what I'm doing wrong.

1) I wasn't using extern "C" for my library functions, so dlsym was unable to find the function.

2) I didn't know that dynamic libraries had to be compiled << pretty stupid of me.

I still want to know if there is a way to use uncompiled code as a library, but my initial problem was solved, thanks to everyone.

Upvotes: 1

Petr Skocik
Petr Skocik

Reputation: 60068

It works fine for me. I've compiled dynlib.so with

$ gcc dynlib.c -fPIC -shared -o dynlib.so

(Obviously, you need to either compile it as C or C++ with extern "C" to avoid name mangling).

and I needed to place -ldl after the source file in the g++ invocation.

gcc: 4.8.5; g++: 5.3.0


dlsym may fail too and casting from void* to function pointers is technically UB. You should base it on the usage snippet from the manpage(modified for your function):

       dlerror();    /* Clear any existing error */

       /* Writing: func = (int (*)(int)) dlsym(handle, "getInt");
          would seem more natural, but the C99 standard leaves
          casting from "void *" to a function pointer undefined.
          The assignment used below is the POSIX.1-2003 (Technical
          Corrigendum 1) workaround; see the Rationale for the
          POSIX specification of dlsym(). */

       *(void **) (&func) = dlsym(handle, "getInt");

       if ((error = dlerror()) != NULL)  {
           fprintf(stderr, "%s\n", error);
           exit(EXIT_FAILURE);
       }

Upvotes: 3

Related Questions