Ошибка создания динамической библиотеки c ++ - PullRequest
2 голосов
/ 10 июня 2011

У меня есть два файла: 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_ */

Я создаю .so файл с: g ++ -shared -o RollDice.so RollDice.cpp

И теперь в моем приложении я хочу открыть этот плагин:

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

Но я получаю сообщение: Невозможно загрузить библиотеку: ./RollDice.so: неверный заголовок ELF

Можете ли вы помочь мне решить эту проблему?

-fPIC

не помогает

Edit:

Теперь я создаю плагин с:

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

и у меня новая проблема: Невозможно загрузить символ create: ./RollDice.so: неопределенный символ: create

Когда я использую nm, чтобы увидеть, какие символы есть в RollDice.so, я не вижу «создать»

Ответы [ 4 ]

2 голосов
/ 10 июня 2011

Одна вещь, которую нужно проверить, которая, кажется, еще не упоминалась, - это то, что точное имя 'create' должно быть экспортировано из вашей общей библиотеки.

Попробуйте

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

Если вы не нашли совпадений или получили какой-то изуродованный символ для 'create', то ваш вызов dlsym (..., "create") обязательно завершится неудачей.

Кроме того, после того, как вы решите проблемы с поиском имен, вы должны серьезно подумать о добавлении RTLD_GLOBAL к своим флагам dlopen. dlopen по умолчанию - RTLD_LOCAL, который плохо взаимодействует с общими библиотеками C ++ w.r.t. RTTI, исключения, typeinfo и т. Д. RTLD_GLOBAL приведет к меньшему количеству сюрпризов.

Также рассмотрите возможность использования RTLD_NOW, а не RTLD_LAZY. Если в вашей библиотеке плагинов есть символы, которые нельзя было разрешить во время добавления, вы только что создали бомбу замедленного действия. Лучше знать в рабочее время, была ли библиотека в состоянии удовлетворить все необходимые ссылки или нет.

редактирование:

Я упустил из виду, что проверка 'create' с 'nm' уже была предложена. Тем не менее, совет по поводу флагов dlopen по-прежнему важен.

Кроме того, ваша строка компиляции выглядит очень странно для меня, особенно в том, что вы включаете RollDice.h в строку сборки, а не файл RollDice.cpp.

Кроме того, включение файлов .cpp в другие файлы .cpp не является стандартной практикой.

Я бы предложил исключить включение .cpp в .cpp, а затем скомпилировать различные файлы .cpp отдельно с -o, а затем объединить их в общую библиотеку:

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
1 голос
/ 10 июня 2011

Не знаю, в чем проблема, но такие инструменты, как readelf и objdump могут предоставить информацию о состоянии двоичного файла, которая может помочь вам решить ваши проблемы.

1 голос
/ 10 июня 2011

Вы не создавали свою разделяемую библиотеку, используя -fPIC для создания независимого от позиции кода, который требуется IIRC для разделяемых библиотек.

Быстрый Google укрепляет мою догадку: http://www.fpx.de/fp/Software/tcl-c++/tcl-c++.html

Так что используйте:

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

И посмотри, поможет ли это.

Другая причина, которая вызывает ошибки такого рода, - это когда вы пытаетесь использовать библиотеки, созданные для разных архитектур (например, ARM, 32, 64 и т. Д.), Но я предполагаю, что вы не собираете плагин. среда, отличная от той, в которой вы компилируете основную программу.

0 голосов
/ 10 июня 2011

Здесь у вас есть ответ

C ++ dlopen mini HOWTO

У вас проблема с методами подписи класса

...