Wie überprüfe ich, ob eine Funktion in C/C++ existiert?

Lesezeit: 7 Minuten

Benutzer-Avatar
Wer bin ich

In bestimmten Situationen in meinem Code rufe ich die Funktion nur auf, wenn diese Funktion definiert ist, oder ich sollte es nicht tun. Wie kann ich das erreichen?

like:
if (function 'sum' exists ) then invoke sum ()

Vielleicht anders herum, um diese Frage zu stellen, wie kann man feststellen, ob die Funktion zur Laufzeit definiert ist, und wenn ja, dann aufrufen?

  • Sie müssten irgendeine Art von ladbarer Bibliotheksunterstützung verwenden, zB dlopen

    – Irgendein Korn

    11. Januar 2012 um 5:47 Uhr

  • Wie genau schlagen Sie vor, in eine Situation zu kommen, in der Sie anrufen möchten? sum aber sind nicht sicher, ob es existiert? Sie sollten wissen, ob es existiert; Du bist derjenige, der den Code schreibt!

    – Karl Knechtel

    11. Januar 2012 um 6:14 Uhr

  • Du solltest wirklich erklären, warum du fragst. In welchem ​​Zusammenhang braucht man das? Das habe ich in 35 Jahren Programmieren in keiner kompilierten Sprache gebraucht …

    – Basile Starynkevitch

    11. Januar 2012 um 6:21 Uhr

  • Ich erhalte den Funktionsnamen als Parameter von der Befehlszeile und muss ihn ausführen, falls vorhanden.

    – Wer bin ich

    11. Januar 2012 um 6:21 Uhr

  • @whoami: In diesem Fall musst du so etwas tun if(string(argv[1]) == "sum") { sum(); }.

    – Naveen

    11. Januar 2012 um 6:24 Uhr

Benutzer-Avatar
matu

Wenn Sie “Summe” deklarieren, können Sie es wie folgt deklarieren:

#define SUM_EXISTS
int sum(std::vector<int>& addMeUp) {
    ...
}

Wenn Sie es dann verwenden, können Sie Folgendes tun:

#ifdef SUM_EXISTS
int result = sum(x);
...
#endif

Ich vermute, Sie kommen aus einer Skriptsprache, in der alles zur Laufzeit erledigt wird. Das Wichtigste, woran man sich bei C++ erinnern sollte, sind die zwei Phasen:

  • Kompilierzeit
    • Präprozessor läuft
    • Vorlagencode wird in echten Quellcode umgewandelt
    • Quellcode wird in Maschinencode umgewandelt
  • Laufzeit
    • Der Maschinencode wird ausgeführt

Also alle #define und solche Dinge passieren zur Kompilierzeit.

….

Wenn Sie wirklich alles zur Laufzeit erledigen wollten, könnten Sie daran interessiert sein, einige der zu verwenden Komponentenarchitekturprodukte dort draußen.

Oder vielleicht ein Plugin-Art von Architektur ist, was Sie suchen.

  • Es ist unglaublich dumm, dass C++ ein solches Pragma nicht bereits im Standard enthält. C++-Header-Dateien enthalten normalerweise eine Million Hacks, um damit umzugehen. Eine Giid-Spezifikation könnte sogar typspezifisch sein. #ifhave(sum(std::vector)). Ich würde C ++ 11 nur für dieses eine Feature verschrotten …

    – Erik Aronesty

    2. Februar 2015 um 14:10 Uhr

  • Als Antwort auf @ErikAronesty – ich wechsle jetzt von c++ zu Rost – Ich finde es viel lustiger 🙂

    – matu

    27. August 2019 um 23:49 Uhr

  • Sie haben dieselbe Seite zweimal verlinkt, war das Absicht? Wie auch immer, der Link war tot, ich habe ihn mit der aktuellen Version aktualisiert.

    – Fabio sagt, Monica wieder einzusetzen

    Vor 2 Tagen

Benutzer-Avatar
Basile Starynkevitch

Während andere Antworten hilfreiche Ratschläge sind (dlsymFunktionszeiger, …), Sie kann nicht kompilieren C++-Code, der auf eine Funktion verweist, die nicht existiert. Die Funktion muss mindestens sein erklärt; Wenn dies nicht der Fall ist, wird Ihr Code nicht kompiliert. Wenn nichts (eine Kompilierungseinheit, eine Objektdatei, eine Bibliothek) definiert die Funktion würde der Linker bemängeln (es sei denn, er ist schwach, siehe unten).

Aber du solltest wirklich erklären, warum du das fragst. Ich kann es nicht erraten, und es gibt einen Weg, Ihr unausgesprochenes Ziel zu erreichen.

Beachte das dlsym erfordert oft Funktionen ohne Namensverstümmelungdh deklariert als extern "C".

Wenn Sie unter Linux mit GCC programmieren, können Sie auch die weak Funktionsattribut bei Deklarationen. Der Linker würde dann undefinierte schwache Symbole auf null setzen.

Nachträge

Wenn Sie den Funktionsnamen aus einer Eingabe erhalten, sollten Sie sich darüber im Klaren sein, dass nur eine Teilmenge von Funktionen auf diese Weise aufrufbar sein sollte (wenn Sie eine beliebige Funktion ohne Sorgfalt aufrufen, stürzt sie ab!) und Sie sollten diese Teilmenge besser explizit konstruieren . Dann könntest du a verwenden std::mapoder dlsym (wobei jede Funktion in der Teilmenge deklariert ist extern "C"). Beachte das dlopen mit einer NULL Pfad gibt dem Hauptprogramm ein Handle, mit dem Sie verknüpfen sollten -rdynamic damit es richtig funktioniert.

Sie möchten wirklich nur eine geeignet definierte Teilmenge von Funktionen mit ihrem Namen nennen. Zum Beispiel möchten Sie wahrscheinlich nicht auf diese Weise anrufen abort, exitoder fork.

NB. Wenn Sie wissen dynamisch die Signatur der aufgerufenen Funktion, die Sie vielleicht verwenden möchten libffi um es zu nennen.

  • Ein weiterer Ansatz für C++ (aber nicht C) SFINAE mit Vorlagen: stackoverflow.com/questions/257288/…

    – fredbaba

    1. August 2013 um 18:58 Uhr

  • Ich habe eine Abstraktion, die von einer Operatorüberladung profitiert. Somit wird der Standardoperator zur Kompilierzeit definiert. Wenn die Operatorüberladung vorhanden ist, möchte ich sie zur Laufzeit erkennen.

    – Ergohack

    13. Dezember 2016 um 18:21 Uhr

  • Das Überladen von @ergohack C++ erfolgt vollständig während der Kompilierzeit und hängt von der Verstümmelung von Symbolnamen ab, die nicht durch den C++-Sprachstandard festgelegt ist (es hängt vom verwendeten Compiler und seiner Version ab).

    – Datenwolf

    30. April 2021 um 18:59 Uhr

Mit GCC können Sie:

void func(int argc, char *argv[]) __attribute__((weak)); // weak declaration must always be present

// optional definition:
/*void func(int argc, char *argv[]) { 
    printf("ENCONTRE LA FUNC\n");
    for(int aa = 0; aa < argc; aa++){
        printf("arg %d = %s \n", aa, argv[aa]);
    }
}*/

int main(int argc, char *argv[]) {
    if (func){ 
        func(argc, argv); 
    } else {
        printf("no encontre la func\n");
    }
}

Wenn Sie func auskommentieren, wird es ausgeführt, andernfalls wird “no encontre la func\n” ausgegeben.

Benutzer-Avatar
fredbaba

Ich vermute, dass das Poster tatsächlich nach etwas mehr in der Art von SFINAE-Prüfung / -Versand gesucht hat. Mit C++-Vorlagen können Vorlagenfunktionen definiert werden, eine, die die gewünschte Funktion aufruft (falls vorhanden) und eine, die nichts tut (falls die Funktion nicht vorhanden ist). Sie können dann die erste Vorlage von der gewünschten Funktion abhängig machen, sodass die Vorlage schlecht geformt ist, wenn die Funktion nicht vorhanden ist. Dies ist gültig, da in C++ ein Fehler bei der Vorlagenersetzung kein Fehler ist (SFINAE), sodass der Compiler einfach auf den zweiten Fall zurückgreift (der beispielsweise nichts tun könnte).

Ein hervorragendes Beispiel finden Sie hier: Ist es möglich, eine Vorlage zu schreiben, um die Existenz einer Funktion zu überprüfen?

Verwenden Sie Zeiger auf Funktionen.

 //initialize
 typedef void (*PF)();
 std::map<std::string, PF> defined_functions;
 defined_functions["foo"]=&foo;
 defined_functions["bar"]=&bar;
 //if defined, invoke it
 if(defined_functions.find("foo") != defined_functions.end())
 {
     defined_functions["foo"]();
 }

  • Dies ist eindeutig die Lösung, wenn ich das OP richtig interpretiere und er wirklich versucht, eine grobe interaktive Shell zu erstellen.

    – Arne

    11. Januar 2012 um 6:30 Uhr

Wenn Sie wissen, in welcher Bibliothek sich die Funktion befindet, die Sie aufrufen möchten, können Sie sie verwenden dlsym() und dlerror() um herauszufinden, ob es da ist oder nicht, und was der Zeiger auf die Funktion ist.

Bearbeiten: Ich würde diesen Ansatz wahrscheinlich nicht wirklich verwenden – stattdessen würde ich Matius Lösung empfehlen, da ich denke, dass dies eine viel bessere Übung ist. Jedoch, dlsym() ist nicht sehr bekannt, also dachte ich, ich würde darauf hinweisen.

  • Dies ist eindeutig die Lösung, wenn ich das OP richtig interpretiere und er wirklich versucht, eine grobe interaktive Shell zu erstellen.

    – Arne

    11. Januar 2012 um 6:30 Uhr

Benutzer-Avatar
matu

Sie können verwenden #pragma weak für die Compiler, die es unterstützen (siehe die schwaches Zeichen Wikipedia-Eintrag).

Dieses Beispiel und dieser Kommentar stammen von Die Insider-Geschichte zu gemeinsam genutzten Bibliotheken und dynamischem Laden:

#pragma weak debug
extern void debug(void);
void (*debugfunc)(void) = debug;
int main() {
    printf(“Hello World\n”);
    if (debugfunc) (*debugfunc)();
}

Sie können das schwache Pragma verwenden, um den Linker zu zwingen, nicht aufgelöste Symbole zu ignorieren [..] das Programm kompiliert und verlinkt, ob debug() tatsächlich in einer Objektdatei definiert ist oder nicht. Wenn das Symbol undefiniert bleibt, ersetzt der Linker normalerweise seinen Wert durch 0. Daher kann diese Technik eine nützliche Möglichkeit für ein Programm sein, optionalen Code aufzurufen, der nicht die Neukompilierung der gesamten Anwendung erfordert.

  • Für mich wird dies in Clang kompiliert, aber der Linker gibt einen Fehler aus: "debug()", referenced from: _debugfunc in test-fc106e.o. ld: symbol(s) not found for architecture x86_64

    – Kritzikratzi

    7. August 2017 um 11:14 Uhr

1019110cookie-checkWie überprüfe ich, ob eine Funktion in C/C++ existiert?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy