Wie kann man deutlich machen, dass von außen auf eine Funktion zugegriffen wird?

9

Dies ist eine C-spezifische Frage. Ich versuche, alles Mögliche innerhalb der Grenzen der Übersetzungseinheit zu halten und nur wenige Funktionen in der .hDatei verfügbar zu machen. Das heißt, ich staticverknüpfe Objekte auf Dateiebene.

Jetzt müssen einige Funktionen von anderen Modulen aufgerufen werden, jedoch nicht direkt. Mein Modul / meine Datei / meine Übersetzungseinheit abonniert die anderen Module und übergibt einen Zeiger auf eine Funktion. Bei einem bestimmten Ereignis wird der Zeiger dann mit einigen Argumenten aufgerufen.

Ich frage mich also, wie ich sehr deutlich machen kann, dass diese Funktionen von einem dunklen Ort aus aufgerufen werden.

  • Sollten sie sein staticoder extern(und sie in der .h) aussetzen ?
  • Sollte ich dem Namen der Funktionen einen Hinweis hinzufügen?
  • Oder reicht es aus, einen Kommentar "von X aufgerufen" zu setzen?
Vorac
quelle
1
Das ist eine ausgezeichnete Frage. Meine Lösung (mit der ich überhaupt nicht zufrieden bin, deshalb schreibe ich sie nur in einen Kommentar) besteht darin, mehrere Header-Dateien mit vernünftigen Namen und Gruppierungsfunktionen in dem Bereich zu erstellen, den sie haben sollen. Für die AStar-Bibliothek, die ich erstellt habe, habe ich AStar.h, AStar_private.h, AStar_packagePrivate.h usw.
Shivan Dragon

Antworten:

2

Aus Sicht der Kompilierungseinheit (Datei) sollten Sie sich nur darum kümmern, ob die Funktion nach außen verfügbar ist oder nicht. Wenn Sie es verfügbar machen, bedeutet dies, dass es angerufen werden soll, und Sie sollten davon ausgehen, dass diese Anrufe stattfinden werden. Ihre Beschäftigung mit der Funktion selbst beginnt am Einstiegspunkt. Wie die Kontrolle überhaupt dorthin gelangt, ist nur für den Code von Bedeutung, der sie ermöglicht.

Da die Verknüpfung in jeder bekannten Implementierung von CI symbolisch ist, muss sich alles, was eine Funktion aufruft, auf ihr Symbol beziehen:

foo();  /* Direct */

some_function_pointer_t funcs[] = { &foo, &bar, &baz };  /* Indirect */

Wenn Sie dies fälschlicherweise angeben foo(), staticwird Ihr Programm nicht verknüpft. Wenn Sie es als nicht deklarieren static, haben Sie eine exponierte Funktion, die nicht aufgerufen wird. Fragen, ob eine Funktion verwendet wird oder nicht, können gelöst werden, indem Sie die Symboltabellen Ihrer Objektdateien sichern oder in den Quellen danach suchen.

Blrfl
quelle
1

Ich überlege mir also, wie ich deutlich machen kann, dass diese Funktionen von einem unbekannten Ort aus aufgerufen werden.

Definieren Sie "obskur".
Methoden sollten gut definierten „Schnittstellen“ ausgesetzt durch und als Shivan Drache hat bereits vorgeschlagen, diese „Schnittstellen“ sind Ihre H - Dateien. Wenn Sie einem anderen Programm nicht die "richtige" Header-Datei geben, kann es die Methode nicht aufrufen.

Sollten sie statisch oder extern sein (und sie in der .h aussetzen)?

static ist möglicherweise in Ordnung, solange Sie keine Klasse [-ähnliche Konstrukte] haben, die Instanzdaten enthalten.
externbedeutet, dass Sie es überhaupt nicht implementieren; Eine Implementierung wird während des Verknüpfungsprozesses von einer anderen Stelle "erworben".

Sollte ich dem Namen der Funktionen einen Hinweis hinzufügen?

Oder reicht es aus, einen Kommentar "von X aufgerufen" zu setzen?

Absolut nicht.

Kommentare wie diese, egal wie gut sie gemeint sind, sind veraltet, sobald Sie mit dem Schreiben fertig sind.

Phill W.
quelle
Um Ihren ersten Punkt anzusprechen, werden die Funktionen wie folgt aufgerufen. Meine Komponente enthält eine externe .hDatei. Von dort ruft es eine Funktion auf und gibt ihr einen Zeiger auf eine der eigenen Funktionen des Moduls. Später ruft der externe Code alles auf, was sich an diesem Zeiger befindet. Daher wird meine Funktion von jemandem aufgerufen, der meine Header-Datei nicht enthält, sondern seine.
Vorac
1
In Bezug auf den zweiten Punkt haben nach meinem Verständnis Objekte, die im Dateibereich definiert sind, standardmäßig eine externe Verknüpfung. daher ist das externSchlüsselwort redundant " .
Vorac
0

Wenn in Ihrem Modul Rückruffunktionen definiert sind und der Benutzer niemals eine eigene bereitstellt, können Sie während der Initialisierungsphase einen Platzhalter verwenden. Der Platzhalter ist normalerweise ein Platzhalter, enumder dann intern in die richtige staticFunktion übersetzt wird.

Lorcap
quelle
0

Ich würde staticsie immer noch erstellen (sie sollen nicht mit irgendjemandem verknüpft und von irgendjemandem aufgerufen werden) und ihren Zweck als Rückrufe markieren, die in ihrem Namen an externe Funktionen gesendet werden.

static weil ich versuche zu verbergen, was ich verstecken kann, so viel ich es verstecken kann.

Markieren Sie sie in ihrem Namen, da a) Kommentare veraltet sind und b) an der Stelle, an der der Rückruf erfolgt, deutlich wird, dass diese Funktion auf diese Weise verwendet werden soll: Dies macht sie im Grunde zu einer roten Fahne Nehmen Sie die Adresse einer Funktion, die nicht der Namenskonvention entspricht.

Sebastian Redl
quelle
0

Bereichsmodifikatoren sollten in erster Linie als Informationen für den Compiler verwendet werden, nicht als Form einer "nah genug" Dokumentation. staticInsbesondere die Verwendung von ermöglicht es einem C-Compiler, die Funktion von außerhalb des Moduls unbrauchbar zu machen, auch als Rückruf - nicht das, was Sie wollen, obwohl sie möglicherweise mit Ihrem aktuellen Compiler funktioniert.

Natürlich sollten Sie dem Code einen Kommentar hinzufügen, da Sie sehen können, dass dies eine möglicherweise verwirrende Situation ist. Alles Ungewöhnliche oder Unerwartete braucht einen passenden Kommentar. Wie in anderen Antworten angegeben, können Kommentare jedoch ungelesen oder veraltet sein.

Die einzige verbleibende Option besteht darin, die Funktion zu benennen, um anzuzeigen, dass es sich um einen Rückruf handelt. Die meisten Beispiele, die ich gesehen habe, verwenden _callbackoder _cbals Suffix oder cb_als Präfix. Verwenden Sie die Langform, wenn Rückrufe in Ihrem Code ungewöhnlich sind, die Kurzform, wenn sie häufig sind.

Jonathan Giddy
quelle