Lokale Funktionen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
dl5eu
Beiträge: 33
Registriert: Do 12. Sep 2013, 12:40

Lokale Funktionen

Beitrag von dl5eu »

Hallo liebe Forumsmitglieder,

nachdem ich bei meinen Suchen bisher keine zufriedenstellende Antwort gefunden habe versuche ich hier mein Glück.

Ich suche eine Möglichkeit, normale Funktionen in einer Unit als nur in dieser sichtbar zu deklarieren, so wie es mit "static" in C möglich ist. Natürlich kann ich die Funktionen einfach in den Implementationsteil schreiben. Allerdings deklariere ich gerne alle Funktionen zunächst einmal "en bloc" und implementiere sie später, so wie es normalerweise in einer Unit erfolgt (Deklaration im Interfaceteil, Implementation im Implementationsteil). Dann ist es nämlich egal, in welcher Reihenfolge die Funktionen in der Datei stehen, wenn sie sich gegenseitig aufrufen (nur lokal sichtbare Funktionen kommen dabei bei mir z.B. immer am Ende der Datei).

In der Dokumentation habe ich den Modifier "local" gefunden. Damit funktioniert es aber bei mir nicht. Außerdem soll er unter Windows keine Wirkung haben. Kennt Ihr eine Möglichkeit, das gewünschte Ziel zu erreichen oder geht das in Free Pascal nicht? Ich weiß, dass nicht alles, was in C möglich ist, auch in Pascal möglich ist.

Vielen Dank für Eure Hilfe!

Ralf

aro
Beiträge: 130
Registriert: Di 26. Jul 2011, 19:58
OS, Lazarus, FPC: Deepin 20.2; Lazarus 2.0.0 + dfsg-2
CPU-Target: 64Bit

Re: Lokale Funktionen

Beitrag von aro »

Hallo,
ich kann zwar nicht nachvollziehen was Du damit erreichen willst, aber um eine Funktion in eier Unit benutzen zu können, muß sie unter "interface" nicht unbedingt deklariert werden.
Schreibe den Quelltext einfach nach "implementation" und ggf. "uses ...."

Dann können alle nachfolgenden Programmzeilen die Funktion verwenden aber außerhalb der Unit sieht niemand, das die Funktion überhaupt existiert.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1435
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Lokale Funktionen

Beitrag von fliegermichl »

genau aus dem Grund heisst der INTERFACE Teil ja auch so. Weil alles was da steht die "Schnittstelle" der Unit mit dem Rest des Programmes ist.

Du kannst im implementation Teil aber Deine lokalen Funktionen am Block deklarieren und sie erst weiter unten implementieren.
Der Bezeichner dafür heisst forward. Beispiel:

Code: Alles auswählen

 
interface
...
implementation
 
procedure procedure1; forward;
procedure procedure2; forward;
...
 
procedure procedure1;
begin
end;
...
 

dl5eu
Beiträge: 33
Registriert: Do 12. Sep 2013, 12:40

Re: Lokale Funktionen

Beitrag von dl5eu »

Hallo aro,

Danke für Deine Nachricht. Bitte entschuldige, Ich habe mich wohl mal wieder missverständlich ausgedrückt.

Ich weiß, es handelt sich hier um Kosmetik, aber ich habe mir eine bestimmte Ordnung in den Quelltexten angewöhnt, die ich auch in Free pascal gerne beibehalten möchte, wenn dies möglich ist.

Damit eine Funktion A eine Funktion B aufrufen kann, muss Funktion B als erste in der Datei stehen, da sonst der Compiler die Funktion B noch nicht kennt, wenn er Funktion A kompilieren soll. Ich möchte, dass die Position in der Datei keine Rolle spielt. In C mache ich z.B. folgendes:

static void function_a(void);
static void function_b(void);

static void function_a(void)
{
function_b();
}

static void function_b(void)
{
do_something();
}

Dies funktioniert nur, weil dem Compiler mit den ersten beiden Zeilen beide Funktionen bekannt gemacht werden. Fehlen sie, kennt der Compiler function_b noch nicht, wenn er function_a kompilieren will.

Das Gleiche möchte ich in Free Pascal erreichen. Bei Funktionen, die im Interfaceteil deklariert sind, ist das kein Problem. Die sind aber für alle anderen Units sichtbar, die die betroffene Unit verwenden und genau das möchte ich vermeiden, function_a und function_b also verstecken.

Beste Grüße,

Ralf

dl5eu
Beiträge: 33
Registriert: Do 12. Sep 2013, 12:40

Re: Lokale Funktionen

Beitrag von dl5eu »

Hallo fliegermichl,

herzlichen Dank für den Schubs in die richtige Richtung! Wie einfach ist es doch, wenn man weiß, wie es geht :-) Hoffentlich vergesse ich es nicht wieder!

Beste Grüße,

Ralf

Warf
Beiträge: 1909
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Lokale Funktionen

Beitrag von Warf »

Das ist aber nicht das selbe wie static in C.

Static in C bedeutet internal linkage, also das die Symbole nur innerhalb der selben ELF Unit verfügbar sind. Der FPC ist zwar mit dem C ELF Format kompatibel (da es der De Facto Standard unter Unix ist), es ist aber im Gegensatz zu C kein teil der Sprache, daher gibt es solche keywords wie static nicht.
Da Pascal das ganze anders angeht als C wird das aber auch nicht benötigt. Wenn man z.B. in C zwei Funktionen mit dem selben Namen hat (aus zwei ELF units) wird der Linker dir im besten fall einen Fehler werfen, daher benötigt man Static um nur eine der beiden Funktionen zu publishen. In Pascal ist das nicht so, in Pascal sind Symbole an die Unit gebunden (sowie an den Typen), die Funktion FOO: Integer aus Unit Test hat also das Symbol _TEST_$$_FOO$$SMALLINT, wodurch sie eindeutig sind, und es nicht zu der doppelten Symbol Problematik wie in C kommen kann

In der Praxis heißt das, das auch wenn du die Funktionen nur in den Implementation Teil schreibst die Symbole dennoch öffentlich sind:
test.pas:

Code: Alles auswählen

Unit test;
 
interface
implementation
function Foo: Integer;
  Foo := 42;
end;
end.


test.c:

Code: Alles auswählen

static int foo() { return 42; }


Code: Alles auswählen

$> fpc test.pas
$> objdump -t test.o
./test.o:   file format Mach-O 64-bit x86-64
 
SYMBOL TABLE:
0000000000000000 g     F __TEXT,__text   _TEST_$$_FOO$$SMALLINT
$> gcc -c test.c
$> objdump -t test.o
 
./test.o:   file format Mach-O 64-bit x86-64
 
SYMBOL TABLE:


Tatsächlich ist eine Funktion nur in den Implementation teil zu schreiben in C ziemlich vergleichbar mit einer Funktion nur in die C Datei zu schreiben. Der Interface teil in Pascal übernimmt praktisch die selbe aufgabe wie die Header Datei in C (nur das diese vorkompiliert werden und das den kompiliervorgang viel schneller macht)

dl5eu
Beiträge: 33
Registriert: Do 12. Sep 2013, 12:40

Re: Lokale Funktionen

Beitrag von dl5eu »

Hallo Warf,

herzlichen Dank für die Erklärung.

Dieser Unterschied zwischen C und Pascal war mir nicht bekannt und damit auch nicht bewusst. Ich muss auch zugeben, dass ich mich mit den Unterschieden zwischen C und Pascal bisher nicht näher beschäftigt habe. Dass Symbole, die nur im Implementation-Teil stehen trotzdem öffentlich sind wusste ich nicht. Mir fehlt da die Erfahrung. Daher meine Frage: ist das in der Praxis von Bedeutung?

Mein Problem ist jedenfalls gelöst, wenn die Funktionen nur im Implementation-Teil stehen, da ich sie dann aus einer anderen Unit nicht aufrufen kann. In C verwende ich dazu "static". Mir ging es darum, die im Interface-Teil veröffentlichten und damit aus anderen Units aufrufbaren Funktionen von denen zu trennen, die ausschließlich lokal, also innerhalb ein und derselben Unit, verwendet werden.

Viele Grüße und einen schönen Abend wünscht

Ralf

Warf
Beiträge: 1909
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Lokale Funktionen

Beitrag von Warf »

dl5eu hat geschrieben:Daher meine Frage: ist das in der Praxis von Bedeutung?

Mein Problem ist jedenfalls gelöst, wenn die Funktionen nur im Implementation-Teil stehen, da ich sie dann aus einer anderen Unit nicht aufrufen kann. In C verwende ich dazu "static". Mir ging es darum, die im Interface-Teil veröffentlichten und damit aus anderen Units aufrufbaren Funktionen von denen zu trennen, die ausschließlich lokal, also innerhalb ein und derselben Unit, verwendet werden.

Viele Grüße und einen schönen Abend wünscht

Ralf


Kurze Antwort, nein, in der Praxis ist das nicht von Bedeutung.

Lange Antwort, der Grund warum man bei C static (Funktionen) benötigt ist das es nicht zwei mal eine Funktion mit gleichen Namen geben darf. Bei Pascal dürfen zwei Units nicht den Selben Namen haben und da Funktionen an die Units gebunden sind bedeutet das das zwei Funktionen mit dem selben Namen in Unterschiedlichen Units verwendet werden können.

Problematisch kann es nur werden wenn man C units und FPC Units separat zu objectfiles kompiliert und die dann gegenlinkt wie hier beschrieben, und man in C zufällig eine Funktion TEST_$$_FOO$$SMALLINT nennst (diese Namensgebung ist in C erlaubt), dann würde der Linker natürlich auch da Alarm schlagen. Sollte praktisch aber nicht vorkommen

Antworten