Wie kann ich eine C ++ Funktion aus einer Zeichenfolge aufrufen?
Rufen Sie stattdessen die Methode direkt aus string:
auf %Vor%In C # würden wir typeof () verwenden und dann die Methodeninformationen abrufen und von dort aufrufen ... alles, was wir in C ++ verwenden können?
Erstellen Sie eine std :: map aus Strings und Funktionszeigern. Erstellen Sie die Karte mit allen Funktionen, die Sie aufrufen möchten.
Es gibt andere Möglichkeiten, dies zu tun, die Symboltabellen und dynamische Lader beinhalten, aber diese Wege sind nicht portabel oder freundlich.
Sie können auch die Antworten auf Wie kann ich Reflektionen hinzufügen? an eine C ++ - Anwendung? für Informationen zu RTTI, dem Reflektionsmechanismus in C ++.
Viel Glück.
Es gibt keinen guten Weg, automatisch zu tun, was Sie fragen. Ich würde zwei verschiedene Möglichkeiten in Betracht ziehen, abhängig davon, wie viele Funktionen Sie benötigen, um aufgerufen zu werden:
Wenn es nur ein paar Funktionen gibt, bleiben Sie bei dem Code, den Sie haben (wenn Sie const char * verwenden möchten, können Sie diese Zeichenfolgen nicht mit dem Operator == vergleichen. Sie können "strcmp ()" verwenden , indem Sie "#include & lt; cstring & gt;") ausführen.
Wenn es viele Funktionen gibt oder wenn Sie häufig Funktionen aus Ihrer Liste hinzufügen und entfernen, sollten Sie "std :: map" verwenden. Dies wird die Funktionsnamen-Zeichenfolge einem Funktionszeiger zuordnen. Ich würde dies wahrscheinlich in eine Klasse für die Benutzerfreundlichkeit einfügen:
%Vor%In reinem Standard C ++ 11 können Sie dieses Ziel nicht wirklich erreichen (Aufruf einer Funktion von seiner Name, der zur Laufzeit durch eine beliebige Zeichenkette vergeben wird), wenn Sie aus dem Funktionsnamen jede beliebige mögliche Funktion Ihres Programms (oder der von ihm verwendeten Bibliotheken) aufrufen wollen. Sie könnten in der Tat einen Dolmetscher einbetten (zB Lua oder ) GNU Guile ), wie von xtofls Antwort vorgeschlagen.
Wenn Sie die Menge der potenziell aufrufbaren Funktionen kennen und eine gemeinsame Signatur teilen (zB typedef int signature_T(int[])
, könnten Sie einfach eine Assoziation von Namen zu Funktionen verwenden, zB einige std::map<std::string,std::function<signature_T>>
; BTW, die neuen Features von C ++ 11 (closures, std::function
, auto
, lambdas) sollte viel helfen.
dlsym
für POSIX Wenn Sie sich auf ein POSIX-System wie Linux beschränken, können Sie einen anderen Trick in Erwägung ziehen: Verwenden Sie dlsym (3) und dlopen (3) , um einen Funktionszeiger zu erhalten von einigen unmigrierten Namen . Also würden Sie die Funktionen, die Sie nennen möchten, durch ihren Namen als extern "C"
deklarieren (um name mangling zu deaktivieren) Verknüpfen Sie Ihr Programm mit -rdynamic
und mit der -ldl
-Bibliothek. Sie würden entweder Plugins mit dlopen
-oder erhalten das Hauptprogramm Handle von dlopen
-ing NULL
- und holen Sie einen Funktionszeiger aus seinem Namen mit dlsym
. Lesen Sie C ++ dlopen mini howto und Dreppers Schreiben freigegebener Bibliotheken Papier.
(Windows hat auch fast gleichwertige Funktionen wie dlsym
, da es auch einen dynamischen Linker hat; aber Ich habe nie Windows benutzt)
Einige C ++ - Framework-Bibliotheken ( Qt , POCO ) wickeln das dynamische Laden von Plugins auf Betriebssystem-unabhängige Weise ab.
libffi
Es gibt ein Problem beim Aufruf von Funktionen der beliebigen Signatur. Sie müssen die Signatur (zumindest zur Laufzeit und oft zur Kompilierzeit) unbedingt wissen, wenn Sie eine Funktion in (oder von) C oder C ++ aufrufen (weil die ABI diktiert verschiedene Aufrufkonventionen ). Sie könnten die libffi verwenden:
Einige Programme wissen zum Zeitpunkt der Kompilierung möglicherweise nicht, welche Argumente an eine Funktion übergeben werden sollen. Zum Beispiel kann ein Interpreter zur Laufzeit über die Anzahl und Typen von Argumenten informiert werden, die zum Aufrufen einer gegebenen Funktion verwendet werden. Libffi kann in solchen Programmen verwendet werden, um eine Brücke vom Interpreterprogramm zum kompilierten Code zu bieten.
Endlich könntest du zur Laufzeit etwas Maschinencode mit Hilfe einiger JIT-Bibliotheken erzeugen: einfache JIT-Bibliotheken wie GNU blitz , libjit , asmjit sind in der Lage, schnell etwas langsamen Maschinencode oder komplexe Compiler-basierte JIT-Frameworks wie libgccjit oder LLVM , die optimiert und generiert werden schneller Maschinencode (benötigt aber eine signifikante Generierungszeit, wie ein Compiler).
dlopen
-ing es Ein zugehöriger Trick würde einfach C- oder C ++ - Code in einer temporären Datei /tmp/foobar.c
generieren, eine Kompilation davon in ein Plugin abzweigen (also nach positionsunabhängiger Code ) mit gcc -fPIC -O -shared /tmp/foobar.c -o /tmp/foobar.so
, dann lade dieses temporäre Plugin dynamisch mit dlopen
. Ich verwende einen solchen Trick in MELT (eine lispy-domänenspezifische Sprache, um GCC , verfügbare freie Software GPLv3).In der Praxis sind Compiler heutzutage schnell genug, um eine solche Verwendung sogar interaktiv zuzulassen: Der Benutzer könnte einen einfachen Ausdruck in ein DSL eingeben, die Infrastruktur übersetzt diesen DSL in C-Code und verzweigt dann in ein Plugin, das später% co_de ist % -ed. Dies ist in der Praxis schnell genug für eine interaktive Verwendung (da der generierte C-Code einige hundert Zeilen pro interaktivem Ausdruck aufweisen würde und das Kompilieren einen Bruchteil einer Sekunde benötigt).
Einige Programmiersprachen sind homoikonisch und / oder haben einige dlopen
Einrichtung oder aktivieren mehrstufige Programmierung . Einige Implementierungen haben sogar die Möglichkeit, zur Laufzeit einen recht effizienten Maschinencode zu generieren, insbesondere SBCL übersetzt jeden Ausdruck in Maschinencode, selbst in seinen < a href="https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop"> Lese-Eval-Druckschleife .
Sie könnten Ihre Funktionsdeklarationen in eine interpretierte Sprache (wie Lua oder Perl oder Python ) umwandeln (boost hat dafür einen schönen Rahmen) ) ). Verwenden Sie dann diese Sprache, um Ihren Code "per String" aufzurufen.
Diese Sprachen / Wrapper sind dafür geschaffen, solche Dinge zu tun. C ++ ist das nicht, daher werden Sie viel Mühe darauf verwenden, Unterstützung dafür hinzuzufügen.