dlopen () выдает ошибку неразрешенного символа, когда .so пытается использовать класс из основного исполняемого файла.Зачем? - PullRequest
2 голосов
/ 16 декабря 2011

Я нахожусь в Linux, вопрос касается общих объектов классов C ++.

Проблема возникает, когда мои общие объекты пытаются использовать ресурсы, связанные с основным исполняемым файлом.У меня есть следующие коды:

loader.cpp:

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

using namespace std;

int main(int argc, char** argv) {
    for(int i=1; i<argc; ++i) {
        string pth = "./";
        pth.append(argv[i]);
        void* dh = dlopen(pth.c_str(), RTLD_NOW);
        if(dh==NULL) {
            cerr << dlerror() << endl;
            return 1;
        }

        CommonInfo::GetInfoFunc getInfo = (CommonInfo::GetInfoFunc)(dlsym(dh,"getInfo"));
        if(getInfo==NULL) {
            cerr << dlerror() << endl;
            return 1;
        }

        CommonInfo* info = getInfo();
        cout << "INFO: " << info->getX() << endl;
        delete info;
    }
    return 0;
}

CommonInfo.h:

#include <string>

class CommonInfo {
    public:
        typedef CommonInfo* (*GetInfoFunc)();
    private:
        std::string x;
    public:
        CommonInfo(const std::string& nx);
        std::string getX() const;
};

РЕДАКТИРОВАТЬ: я случайно забыл Ctrl-C + Ctrl-v источник CommonInfo.cpp здесь.Конечно, он есть во время компиляции, поэтому CommonInfo.cpp:

#include "CommonInfo.h"

CommonInfo::CommonInfo(const std::string& nx) : x(nx) {
}

std::string CommonInfo::getX() const {
    return x;
}

Заголовок Plugin.h:

#include "CommonInfo.h"
extern "C" CommonInfo* getInfo();

Очень простой Plugin.cpp:

#include <iostream>
#include "Plugin.h"
#include "CommonInfo.h"

using namespace std;

CommonInfo* getInfo() {
    return new CommonInfo("I'm a cat!");
}

Компиляция выполняется с помощью:

g++ -rdynamic -ldl -Werror CommonInfo.cpp loader.cpp -o loader
g++ -shared -fPIC -Werror Plugin.cpp -o Plugin.so

Запуск:

./loader Plugin.so

И возникает ошибка:

./loader: symbol lookup error: ./Plugin.so: undefined symbol: _ZN10CommonInfoC1ERKSs

Действительно, заглядывая внутрь плагина.так что с nm Plugin.so | grep -i CommonInfo он дает «U» для этого символа (неразрешенный), что совершенно нормально.Кроме того, заглянув внутрь двоичного файла загрузчика с nm loader.so | grep -i CommonInfo, я смог найти символ с 'T', что тоже нормально.Вопрос в том, не должен ли dlfcn.h разрешить рассматриваемый символ из основного двоичного файла?Без этой функции становится довольно сложно использовать эти вещи ... Должен ли я написать функцию фабрики классов для CommonInfo, загрузить ее с помощью dlfcn из плагина и вызвать ее?

Заранее спасибо, Деннис

1 Ответ

5 голосов
/ 16 декабря 2011

Я не присматривался к вашему коду, но в прошлом обнаруживал поведение, подобное описанному вами в заголовке, когда я не связывал исполняемый файл с -E.(Или -Wl,-E при связывании с gcc вместо ld.)

Обратите внимание, что не все платформы позволяют разделяемым библиотекам принимать символы из вызывающего двоичного файла.Linux и * BSD позволяют вам.Но если вы захотите портировать, скажем, на Windows, вы не сможете использовать этот шаблон.Я полагаю, что есть также некоторые ОС типа Unix, которые не позволят вам сделать это.(Прошло много времени, поэтому я не помню ... Может быть, это был Солярис?)

...