2

I have two files: RollDice.cpp

#include "RollDice.h"
#include "./IPlugins.cpp"
#include "./IPluginFunctions.cpp"

#include <iostream>

RollDice::RollDice(IPluginFunctions &iPluginFunctions) :
    IPlugins(iPluginFunctions) {
    //srand(time(NULL));
}

RollDice::~RollDice() {

}

void RollDice::callPlugin(std::string paramsText, std::string dataText) {
    std::cout << "RollDice ;)\n";
}

RollDice.h:

#ifndef ROLLDICE_H_
#define ROLLDICE_H_
#include "./IPlugins.h"
#include "./IPluginFunctions.h"

class RollDice: public IPlugins {
public:
    RollDice(IPluginFunctions &iPluginFunctions);
    virtual ~RollDice();

    virtual void callPlugin(std::string paramsText, std::string dataText);
};

extern "C" RollDice* create(IPluginFunctions &iPluginFunctions) {
    return new RollDice(iPluginFunctions);
}

extern "C" void destroy(RollDice *rollDice) {
    delete rollDice;
}

#endif /* ROLLDICE_H_ */

I create .so file with: g++ -shared -o RollDice.so RollDice.cpp

And now in my application I want to open this plugin:

this->plugin = dlopen(directory.c_str(), RTLD_LAZY);
    if (!(this->plugin)) {
        std::cerr << "Cannot load library: " << dlerror() << '\n';
        return;
    }

    dlerror();

    this->createPlugin = (create_p*) dlsym(plugin, "create");
    const char* dlsymError = dlerror();
    if (dlsymError) {
        std::cerr << "Cannot load symbol create: " << dlsymError << '\n';
        return;
    }

    this->destroyPlugin = (destroy_p*) dlsym(plugin, "destroy");
    dlsymError = dlerror();
    if (dlsymError) {
        std::cerr << "Cannot load symbol destroy: " << dlsymError << '\n';
        return;
    }

But I get message: Cannot load library: ./RollDice.so: invalid ELF header

Can you help me solving this?

-fPIC

doesn't help

Edit:

Now I'm bulding plugin with:

g++ -shared -fPIC -o RollDice.so RollDice.h IPlugins.cpp IPluginFunctions.cpp

and I have new problem: Cannot load symbol create: ./RollDice.so: undefined symbol: create

When I use nm to see what symbols are in RollDice.so I don't see "create"

Community
  • 1
  • 1
vesper
  • 155
  • 1
  • 3
  • 9

4 Answers4

2

One thing to check that doesn't seem to have been mentioned yet is that the exact name 'create' must be exported from your shared library.

Try

nm --dynamic --defined-only RollDice.so | grep create

If you get no matches, or get some mangled symbol for 'create', then your dlsym(..., "create") call is bound to fail.

Also, once you solve the name lookup issues, you should seriously consider adding RTLD_GLOBAL to your dlopen flags. dlopen defaults to RTLD_LOCAL, which interacts poorly with C++ shared libraries w.r.t. RTTI, exceptions, typeinfo, etc. RTLD_GLOBAL will lead to fewer surprises.

Also consider using RTLD_NOW rather than RTLD_LAZY. If there are symbols in your plugin library that were not resolvable at dlopen time, you have just created a ticking time bomb. Better to know at dlopen time whether the library was able to satisfy all of the required references or not.

edit:

I overlooked that checking for 'create' with 'nm' had already been suggested. However the dlopen flags advice is still important.

Also, your compilation line looks very odd to me, especially that you are including the RollDice.h on the build line, rather than the RollDice.cpp file.

In addition, including .cpp files in other .cpp files is not standard practice.

I'd suggest eliminating the .cpp to .cpp inclusion, and then compiling the various .cpp files separately with -o, then merging them into a shared library:

g++ -g -fPIC -c -o RollDice.o RollDice.cpp
g++ -g -fPIC -c -o IPluginFunctions.o IPluginFunctions.cpp
g++ -g -fPIC -c -o IPlugins.o IPlugins.cpp
g++ -g -fPIC -shared -o RollDice.so RollDice.o IPluginFunctions.o IPlugins.o
acm
  • 12,183
  • 5
  • 39
  • 68
1

You didn't build your shared lib using -fPIC to produce position independent code, which IIRC is required by shared libraries.

A quick google reinforces my hunch: http://www.fpx.de/fp/Software/tcl-c++/tcl-c++.html

So use:

g++ -shared -fPIC -o RollDice.so RollDice.cpp

And see if that helps.

The other thing that causes errors of that sort are when you are trying to use libraries built for different architectures (eg ARM, 32, 64, etc), but I am assuming you aren't building the plugin .so in a different environment to the one which you are compiling the core program.

benosteen
  • 1,366
  • 7
  • 5
  • I'm building both, my app and plugin, on Ubuntu 11.04 32-bit – vesper Jun 10 '11 at 11:36
  • Is your executable being built with the '-rdynamic' param? eg `g++ -rdynamic etc etc main.c` To go further, you might need to post more details, like your Makefile and so on. – benosteen Jun 10 '11 at 11:53
  • I'm using Eclipse and it builds app with: g++ -rdynamic -O0 -g3 -Wall -c -fmessage-length=0 I built plugin with: g++ -shared -fPIC -o RollDice.so RollDice.h IPlugins.cpp IPluginFunctions.cpp And now I have: Cannot load symbol create: ./RollDice.so: undefined symbol: create – vesper Jun 10 '11 at 12:03
  • Excellent progress :) One thing I do when linking like this may be stylistic and make no difference, but I wrap the functions for extern in a set of braces: `extern "C" { void foo(...) { // stuff in here }; void bar(...) ...... etc }` - it may be pure hocus-pocus and make no difference, but... well, it's an easy thing to try out :) – benosteen Jun 10 '11 at 12:09
  • Unfortunately it didn't make any difference. – vesper Jun 10 '11 at 12:14
  • Ah, sorry! Next, you can use `nm` to see what symbols are actually exported within a given library - try `nm RollDice.so`. You'll get a load of symbols, and you'll be able to see if `create` is among them. – benosteen Jun 10 '11 at 12:23
  • It's not there. I don't see any symbols with "create" in name. – vesper Jun 10 '11 at 12:30
  • It does sound like the library isn't being created properly - I've quickly had a go at doing a basic dynload example to remind myself (admittedly in C) http://pastebin.com/WSrZaz5D - I'll have a go at a C++ one... – benosteen Jun 10 '11 at 12:53
  • I've done a quick C++ version of the dlopen test I did, based on your example code. I've had to fudge the interface includes though, but it links for me: http://pastebin.com/M5VMt4xr – benosteen Jun 10 '11 at 13:51
1

Not sure what the problem is but tools like readelf and objdump might provide information on the state of the binary that may help you resolve your issues.

doron
  • 27,972
  • 12
  • 65
  • 103
0

Here you have the answer

C++ dlopen mini HOWTO

You have a problem with class methods signature

jcalvosa
  • 46
  • 1
  • Why would that break the dlopen? And the two functions he's trying to dlsym are global and `extern "C"` so they ought to work, oughtn't they? – Rup Jun 10 '11 at 13:19