Frage

Was ist der einfachste und sicherste Weg, um eine Funktion von einer gemeinsamen Bibliothek / DLL aus zu bezeichnen? Ich bin hauptsächlich daran interessiert, dies unter Linux zu tun, aber es wäre besser, wenn es einen plattformunabhängigen Weg gäbe.

Könnte jemand einen Beispielcode bereitstellen, um anzuzeigen, wie das folgende funktioniert, wo der Benutzer seine eigene Version von zusammengestellt hat foo in eine gemeinsame Bibliothek?

// function prototype, implementation loaded at runtime:
std::string foo(const std::string);

int main(int argc, char** argv) {
  LoadLibrary(argv[1]); // loads library implementing foo
  std::cout << "Result: " << foo("test");
  return 0;
}

Übrigens, ich weiß, wie man die gemeinsame LIB zusammenstellt (foo.so), Ich muss nur eine einfache Möglichkeit wissen, es zur Laufzeit zu laden.

War es hilfreich?

Lösung

HINWEIS: Sie übergeben C ++ - Objekte (in diesem Fall STL -Zeichenfolgen) um Bibliotheksaufrufe. Es gibt Kein Standard C ++ Abi auf diesem Level, Versuchen Sie daher entweder, C ++-Objekte umzugeben, oder stellen Sie sicher, dass sowohl Ihre Bibliothek als auch Ihr Programm mit demselben Compiler (idealerweise demselben Compiler auf derselben Maschine) erstellt wurden, um subtile Konfigurationsüberraschungen zu vermeiden.

Vergiss nicht Deklarieren Sie Ihre exportierten Methoden extern "C" In Ihrem Bibliothekscode.

Die oben genannten gesagt, hier ist hier Einige Code, die das implementieren, was Sie erreichen möchten:

typedef std::string (*foo_t)(const std::string);
foo_t foo = NULL;

...

# ifdef _WIN32
  HMODULE hDLL = ::LoadLibrary(szMyLib);
  if (!hDll) { /*error*/ }
  foo = (foo_t)::GetProcAddress(hDLL, "foo");
# else
  void *pLib = ::dlopen(szMyLib, RTLD_LAZY);
  if (!pLib) { /*error*/ }
  foo = (foo_t)::dlsym(pLib, "foo");
# endif
  if (!foo) { /*error*/ }

  ...

  foo("bar");

  ...

# ifdef _WIN32
  ::FreeLibrary(hDLL);
# else
  ::dlclose(pLib);
# endif

Du kannst Zusammenfassung dies weiter:

#ifdef _WIN32
#include <windows.h>
typedef HANDLE my_lib_t;
#else
#include <dlfcn.h>
typedef void* my_lib_t;
#endif

my_lib_t MyLoadLib(const char* szMyLib) {
# ifdef _WIN32
  return ::LoadLibraryA(szMyLib);
# else //_WIN32
  return ::dlopen(szMyLib, RTLD_LAZY);
# endif //_WIN32
}

void MyUnloadLib(my_lib_t hMyLib) {
# ifdef _WIN32
  return ::FreeLibrary(hMyLib);
# else //_WIN32
  return ::dlclose(hMyLib);
# endif //_WIN32
}

void* MyLoadProc(my_lib_t hMyLib, const char* szMyProc) {
# ifdef _WIN32
  return ::GetProcAddress(hMyLib, szMyProc);
# else //_WIN32
  return ::dlsym(hMyLib, szMyProc);
# endif //_WIN32
}

typedef std::string (*foo_t)(const std::string);
typedef int (*bar_t)(int);
my_lib_t hMyLib = NULL;
foo_t foo = NULL;
bar_t bar = NULL;

...

  if (!(hMyLib = ::MyLoadLib(szMyLib)) { /*error*/ }
  if (!(foo = (foo_t)::MyLoadProc(hMyLib, "foo")) { /*error*/ }
  if (!(bar = (bar_t)::MyLoadProc(hMyLib, "bar")) { /*error*/ }

  ...

  foo("bar");
  bar(7);

  ...

  ::MyUnloadLib(hMyLib);

Andere Tipps

Lastlibrary ist eine Windows -Funktion zum Laden von DLLs. Sie können nach Symbol existieren mit GetProcaddress. Auf Linux/Unix möchten Sie DLOPEN/dlsym. Um dies in der Cross-Plattform zu tun, können Sie eine Funktion schreiben, die eine dieser Methoden mit Pre-Processor aufruft.

int loadlibrary(char* library)
{
#ifdef _WIN32
    /* do windows code */

#endif
#ifdef _LINUX
    /* do linux code */

#endif
}

Dies ist eine Möglichkeit, solche Dinge zu erreichen. Sie können dies auch tun, indem Sie einen anderen Header in Ihren eigenen Quellbaum für bestimmte Plattformimplementierungen von Funktionen aufnehmen. Dies ist wahrscheinlich ein besserer Weg. In beiden Fällen ist es die Idee, von der zugrunde liegenden API abstrahiert zu werden.

Unter Linux müssen Sie verwenden dlsym. Siehe ein Beispiel am Ende der Seite. Auf Fenster: GetProcaddress.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top