проблема связывания динамической библиотеки - PullRequest
1 голос
/ 03 мая 2011

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

http://www.linuxjournal.com/article/3687?page=0,1

Я создал класс shape и поместил его в отдельную библиотеку (не настоящую библиотеку, так как это просто файл заголовка, но поместил еготаким образом), также я создал две динамические библиотеки, окружность и квадрат, которые наследуются от формы и реализуют метод рисования и регистрируют их функцию создания на заводской карте.Позвольте мне показать вам код:

shape.h:

#ifndef __SHAPE_H
#define __SHAPE_H
#include <map>
#include <string>

// base class for all shapes
class shape{
public:
// our global factory
virtual void draw()=0;
};

// typedef to make it easier to set up our factory
typedef shape *maker_t();
extern std::map<std::string, maker_t *, std::less<std::string> > factory;


#endif // __SHAPE_H

circle.h

#ifndef __CIRCLE_H
#define __CIRCLE_H

#include "shape.h"

class circle : public shape
{
public:
   void draw();
};
#endif // __CIRCLE_H

circle.cpp:

#include <iostream>
#include "circle.h"

void circle::draw()
{
    // simple ascii square
std::cout << "\n";
std::cout << "      ****\n";
std::cout << "    *      *\n";
std::cout << "   *        *\n";
std::cout << "   *        *\n";
std::cout << "   *        *\n";
std::cout << "    *      *\n";
std::cout << "      ****\n";
std::cout << "\n";
}

extern "C"
{
shape *maker()
{
    return new circle;
}
class proxy
{
    public:
        proxy()
        {
            // register the maker with the factory
            factory["circle"] = maker;
        }
};
// our one instance of the proxy
proxy circle_p;
}

Я не буду вдаваться в квадрат, поскольку он почти идентичен кругу и фактическому «клиенту», который динамически загружает библиотеки, поскольку он действительно работает.

Теперь мой вопрос: если у вас есть другие классы и функции в circle.so (это мой случай), а в некоторых случаях вам нужна ссылка во время компиляции (опция -l), я сталкиваюсь спроблемы.Я создал тестовую клиентскую библиотеку, которая вместо динамической загрузки круга делает это во время компиляции.Сбой компоновщика со следующим выводом:

Invoking: GCC C++ Linker
g++ -rdynamic -L/home/lizardking/workspace/dynclientest/Debug/libs -o "test2"  ./src/test2.o   -ldynlib_circle
/home/lizardking/workspace/dynclientest/Debug/libs/libdynlib_circle.so: undefined reference to `factory'
collect2: ld returned 1 exit status

Файл main.cpp из этого тестового приложения - просто привет !:

#include <iostream>
using namespace std;

int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
return 0;
}

Я действительно не знаю, почему компоновщик жалуется на всевремя про карту .... есть идеи ???

спасибо!

Ответы [ 2 ]

0 голосов
/ 03 мая 2011

Если вы внимательно прочитаете ошибку, вы поймете причину ее возникновения.

/ home/lizardking/workspace/dynclientest/Debug/libs/libdynlib_circle.so: undefined reference to factory`

Он сообщает вам, что не может найти ссылку на объект с именем factory, а также указывает место, откуда этот объект получает доступ libdynlib_circle.so

При регистрации libdynlib_circle.so объект factory объявлен как extern в shape.h. Когда вы используете ключевое слово extern для переменной или объекта, он сообщает компилятору, что конкретная переменная или объект будут определены ( созданы ) в некоторых других Исходный файл и место, где он объявлен как extern (shape.so), ссылаются только на одну и ту же переменную. В вашем случае этот factory объект не определен и не создан ни в одном из исходных файлов, и, следовательно, ошибка, undefined reference to factory из-за source.so не может найти созданный factory объект.

Следовательно, чтобы избежать ошибки, вам нужно определить объект factory в одном из исходных файлов.

std::map<std::string, maker_t *, std::less<std::string> > factory;
0 голосов
/ 03 мая 2011

Вы только что объявили factory как extern в shape.h.

Вы должны поместить что-то вроде:

std::map<std::string, maker_t *, std::less<std::string> > factory;

в shape.cpp, чтобы зарезервировать пространство (т.е. создать определенныйсимвол) в shape.o.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...