Динамическая Общая библиотека C++ в Linux

Это продолжение динамическая компиляция общей библиотеки с помощью g++.

Я пытаюсь создать общую библиотеку классов на C++ в Linux. Я могу получить библиотеку для компиляции, и я могу вызвать некоторые (неклассовые) функции, используя учебники, которые я нашел здесь и здесь. Мои проблемы начинаются когда я пытаюсь использовать классы, определенные в библиотеке. Второй учебник, с которым я связан, показывает, как загружать символы для создание объектов классов, определенных в библиотеке, но не используя эти объекты, чтобы получить любую работу.

кто-нибудь знает более полный учебник по созданию общих библиотек классов C++, который также показывает, как использовать эти классы в отдельном исполняемом файле? Очень простой учебник, который показывает создание объектов, использование (простые геттеры и сеттеры были бы в порядке), и удаление было бы фантастическим. Ссылка или ссылка на какой-либо открытый исходный код код, иллюстрирующий использование общей библиотеки классов, был бы одинаково хорош.


хотя ответы codelogic и nimrodm do work, я просто хотел добавить, что я взял копию Начало Программирования Linux поскольку этот вопрос задан, и его первая глава имеет пример кода C и хорошие объяснения для создания и использования как статических, так и общих библиотек. Эти примеры доступны через Google Book Search в старое издание этой книги.

3 ответов


и MyClass.h

#ifndef __MYCLASS_H__
#define __MYCLASS_H__

class MyClass
{
public:
  MyClass();

  /* use virtual otherwise linker will try to perform static linkage */
  virtual void DoSomething();

private:
  int x;
};

#endif

myclass.cc

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

using namespace std;

extern "C" MyClass* create_object()
{
  return new MyClass;
}

extern "C" void destroy_object( MyClass* object )
{
  delete object;
}

MyClass::MyClass()
{
  x = 20;
}

void MyClass::DoSomething()
{
  cout<<x<<endl;
}

class_user.cc

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

using namespace std;

int main(int argc, char **argv)
{
  /* on Linux, use "./myclass.so" */
  void* handle = dlopen("myclass.so", RTLD_LAZY);

  MyClass* (*create)();
  void (*destroy)(MyClass*);

  create = (MyClass* (*)())dlsym(handle, "create_object");
  destroy = (void (*)(MyClass*))dlsym(handle, "destroy_object");

  MyClass* myClass = (MyClass*)create();
  myClass->DoSomething();
  destroy( myClass );
}

в Mac OS X скомпилируйте с помощью:

g++ -dynamiclib -flat_namespace myclass.cc -o myclass.so
g++ class_user.cc -o class_user

в Linux скомпилируйте с помощью:

g++ -fPIC -shared myclass.cc -o myclass.so
g++ class_user.cc -ldl -o class_user

если бы это было для системы плагинов, вы бы использовали MyClass в качестве базового класса и определили все необходимые виртуальные функции. Затем автор плагина производный от MyClass, переопределяет виртуалы и реализует create_object и destroy_object. Ваше основное приложение не нужно будет изменять каким-либо образом.


ниже приведен пример общей библиотеки классов.[h, cpp] и основной.cpp модуль с использованием библиотеки. Это очень простой пример, и makefile может быть сделан намного лучше. Но это работает и может помочь вам:

shared.h определяет класс:

class myclass {
   int myx;

  public:

    myclass() { myx=0; }
    void setx(int newx);
    int  getx();
};

shared.cpp определяет функции getx / setx:

#include "shared.h"

void myclass::setx(int newx) { myx = newx; }
int  myclass::getx() { return myx; }

main.cpp использует класс,

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

using namespace std;

int main(int argc, char *argv[])
{
  myclass m;

  cout << m.getx() << endl;
  m.setx(10);
  cout << m.getx() << endl;
}

и makefile, который генерирует libshared.так и ссылки main с общим библиотека:

main: libshared.so main.o
    $(CXX) -o main  main.o -L. -lshared

libshared.so: shared.cpp
    $(CXX) -fPIC -c shared.cpp -o shared.o
    $(CXX) -shared  -Wl,-soname,libshared.so -o libshared.so shared.o

clean:
    $rm *.o *.so

для фактического запуска "main" и связи с libshared.поэтому вам, вероятно, нужно будет указать путь загрузки (или поместить его в /usr/local/lib или аналогичный).

ниже указан текущий каталог в качестве пути поиска для библиотек и выполняется main (синтаксис bash):

export LD_LIBRARY_PATH=.
./main

чтобы увидеть, что программа связана с libshared.таким образом, вы можете попробовать ldd:

LD_LIBRARY_PATH=. ldd main

отпечатки на моей машине:

  ~/prj/test/shared$ LD_LIBRARY_PATH=. ldd main
    linux-gate.so.1 =>  (0xb7f88000)
    libshared.so => ./libshared.so (0xb7f85000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7e74000)
    libm.so.6 => /lib/libm.so.6 (0xb7e4e000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0xb7e41000)
    libc.so.6 => /lib/libc.so.6 (0xb7cfa000)
    /lib/ld-linux.so.2 (0xb7f89000)

в принципе, вы должны включить файл заголовка класса в код, где вы хотите использовать класс в общей библиотеке. Затем, когда вы связываете,используйте флаг' - l' чтобы связать код с общей библиотекой. Конечно, это требует своего .чтобы быть там, где ОС может найти его. См.3.5. Установка и использование общей библиотеки

использование dlsym - это когда вы не знаете во время компиляции, какую библиотеку хотите использовать. Не похоже, что это дела здесь. Может быть, путаница в том, что Windows вызывает динамически загруженные библиотеки, делаете ли вы связывание во время компиляции или во время выполнения (с аналогичными методами)? Если это так, то вы можете думать о dlsym как эквиваленте LoadLibrary.

Если вам действительно нужно динамически загружать библиотеки (т. е. они являются плагинами), то этот FAQ должно помочь.