Alex Rivera | Logout

Dynamic Shared Library compilation with g++

Asked 2009-01-27T15:16:44.107
17

I'm trying to compile the following simple DL library example code from Program-Library-HOWTO with g++. This is just an example so I can learn how to use and write shared libraries. The real code for the library I'm developing will be written in C++.

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

int main(int argc, char **argv) {
    void *handle;
    double (*cosine)(double);
    char *error;

    handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);
    if (!handle) {
        fputs (dlerror(), stderr);
        exit(1);
    }

    cosine = dlsym(handle, "cos");
    if ((error = dlerror()) != NULL)  {
        fputs(error, stderr);
        exit(1);
    }

    printf ("%f\n", (*cosine)(2.0));
    dlclose(handle);
}

If I compile the program with gcc it works fine.

gcc -o foo foo.c -ldl

When I change the filename and compiler to the following

g++ -o foo foo.cpp -ldl

I get the following error:

foo.cpp:16: error: invalid conversion from 'void*' to 'double (*)(double)'

I understand (I think I understand, correct me if this is wrong) that I can't do an implicit cast from a void pointer in C++, but C lets me, and this is why the above code will compile using gcc but not using g++. So I tried an explicit cast by changing line 16 above to:

cosine = (double *)dlsym(handle, "cos");

With this in place, I get the following error:

foo.cpp:16: error: cannot convert 'double*' to 'double (*)(double)' in assignment

These problems probably have more to do with my own general ignorance of proper C++ coding standards than anything else. Can anyone point me to a good tutorial on developing dynamic libraries for Linux that uses C++ example

Edit
Report

1 Answer

0

With the way your code if written, this is really more of a C question, but you can get this to will work in C++. I don't have a tutorial for you on Dynamic Shared Libraries (the web page you linked to seems fine), but here's how to fix your code in C++:

  • declare my_cos to be a function that will (eventually) call the dynamically loaded cosine function:

    double my_cos(double);
    
  • assign the function pointer to my_cos

    my_cos = (double (*)(double)) dlsym(handle, "cos");
    

This is a little complicated, but it's assigning to my_cos something that returns a double, is the result of dereferencing another function pointer, and takes a double as an argument. As other people have posted, C++ is a little more demanding about the explicitness of your code than C.

  • replace that rather dated fputs message with a std::cerr or std::cout:

    std::cerr << "error loading library cos: " << error << std::endl;
    

and

std::cout << "result is " << (*my_cos)(2.0)) << std::endl;

Hope that this help. If that weird casty stuff scares you, I'd recommend Deep C Secrets by van Linden, and definitely the Kernighan and Ritchie Book on C.

Edit: Good point in the comment about how you're specifically looking for a development guide in C++ rather than C to avoid this type of problem. I don't know of a comparable guide in C++, but about 99% of C code can be embedded in C++ code and work just fine. This function pointer case is one of the exceptions.

answered 2009-01-27T15:39:44.403

Your Answer