Динамични библиотеки

...и имат ли те почва у нас

Какво е динамична библиотека?

  • .dll, .so, .dylib (а също така и executable)
    • same but different
  • CppCon 2017 лекция за DLLs
  • Какъв е смисълът от тях?
  • Видове (C/C++/...)
  • Как се използват?

Как се използват C++?

#if defined(_MSC_VER)
#   define SYMBOL_EXPORT __declspec(dllexport)
#   define SYMBOL_IMPORT __declspec(dllimport)
#else
#   define SYMBOL_EXPORT __attribute__((__visibility__("default")))
#   define SYMBOL_IMPORT
#endif // fuck other compilers

#if defined COMPILING_SHARED_LIB_X
#    define X_API SYMBOL_EXPORT
#else
#    define X_API SYMBOL_IMPORT
#endif

....

class X_API Foo {};

class Bar {
public:
    X_API void barFunc();
};

X_API void func();

// link with me

Мотика: rpath и пътища

  • Windows: каквото е до ехе-то, каквото е в path, manifests
  • Unix: rpath (каквото му кажем)
    • rpath и symbolic links

Мотика: видимост

  • VC: невидими
  • Другите компилатори: видими
    • Умирате от binary size
    • -fvisibility=hidden

Как се използват C?

// dyn lib plugin

extern "C" X_API void foo(int a, float b);


// executable

auto lib = LoadLibrary("foo.dll") / dlopen("foo.so/dylib");
auto func = GetProcAddress("foo") / dlsym(foo);

auto foo = reinterpret_cast<void (*)((int a, float b));

foo(1, 2.3f);

FreeLibrary(lib) / dlclose(lib);
  • Calling конвенции
  • Плъгини
  • Други езици

Мотика: няма експорт на класове от плъгин

Мотика: C++ обекти в extern "C" функции

  • Може и да работи, но по-добре не го рискувайте
  • Предавайте С++ обектите по указател
  • Със сигурност няма да работи с друг език

Мотика: dlclose работи както си ще

Спасение: entry/exit points

 

  • DllMain (attach/detach)
  • _init() / _fini()

Мотика: глобални символи и инстанции на темплейти, и ODR violations

Спасение: дедуплициране

  • Отделни динамични библиотеки за глобалности
  • Експортване на темплейти
    • Мотика: Не работи винаги

Мотика: С плъгина си отива и паметта му

  • Не само експлицитно заделени от нас неща
  • Отиват си и глобалните му променливи
    • Ама заради dlclose гадостите, даже не може да разчитате на това

Спасение:

 

  • Копиране
  • Дедуплициране: паметта идва от един модул
  • Примирение: менажираме си паметта

Мотика: Exceptions

  • Експортвайте винаги
    • VC го прави вместо вас, но пак експортвайте
  • Exceptions от плъгин. Не!
    • Ама...
    • НЕ!

Мотика: static libs, absolute code и relocation

Спасение: -fPIC

  • Linux: Винаги за статични библиотеки, които линквате с динамични
  • -fpic ... never trust -fpic!

Мотика: Same but different

  • Same: динамично зареждане
  • Same: линкване към тях
  • Same: ref counters
  • Same: глобални обекти
  • Same: extern "C" и преизползваемост
  • Different: dlclose (dll/dylib vs so)
  • Different: rpath/LD_LIBRARY_PATH (dll vs dylib/so)
  • Different: динамично алокирана памет (dll/dylib vs so)
  • Different: position independent code (dll/dylib vs so)
  • Different: default visibility (dll vs dylib/so)
  • Different: Entry/exit points (dll vs dylib/so)

Край.

Какво тъпо нещо казах?

Какво пропуснах?