1

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) {.

niraami
  • 646
  • 8
  • 18

2 Answers2

3

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);
       }
Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
  • I added the extern linkage and the error is now *./dynlib.so: invalid ELF header*. ^^ With that I also compiled it with *g++ -std=c++11 -fPIC loadlibtest.cpp -ldl -o main* Both g++ and gcc are 4.8.4. – niraami Jun 15 '16 at 20:01
  • 1
    @areuz Question is, how are you compiling dynlib.so? `g++ -fPIC -shared dynlib.cc -o dynlib.so` where dynlib.cc is the `getInt` definition wrapped in `extern "C"` works for me fine. – Petr Skocik Jun 15 '16 at 20:05
  • In your latest edit, you haven't defined *func*, nor *error*. But I expect *error* to be a char. – niraami Jun 15 '16 at 20:06
  • @areuz `char *error;` (see the linked example in the manpage). The under-the line edit is just language-lawyer nitpicking, though. A brute force cast from a a successfully returned `void*` to function pointer should work on reasonable compilers. – Petr Skocik Jun 15 '16 at 20:10
  • 1
    Your problem appears to be that you're creating the dynlib.so wrong. – Petr Skocik Jun 15 '16 at 20:12
  • 1
    You know when I said I don't know anything about dynamic libraries. Well, I haven't seen someone compiling it before. After I did what you said It worked like a charm. – niraami Jun 15 '16 at 20:12
1

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.

niraami
  • 646
  • 8
  • 18
  • 1
    There is a way to use uncompiled code as shared library. The way is called compilation. ;-) C and C++ aren't languages designed for runtime interpretation. If you're dynamically loaded plugins must be supplied as source, then it's your program needs to compile it for itself first. – Petr Skocik Jun 15 '16 at 20:30
  • @PSkocik Thanks :) I'll look into that, It can't be that hard. – niraami Jun 15 '16 at 20:34