Verschiedene "external"

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Verschiedene "external"

Beitrag von Mathias »

So eine external Deklaration leuchtet mir ein, da wird die Funktion in den *.h im Ordner "X11" gesucht.

Code: Alles auswählen

function XOpenDisplay(para1:Pchar):PDisplay;cdecl;external 'X11';
Jetzt habe ich sowas enrdeckt:

Code: Alles auswählen

    Function  FpNanoSleep  (req : ptimespec;rem : ptimespec):cint; external name 'FPC_SYSC_NANOSLEEP';
Was bedeutet das "name" ?
Und was ist das 'FPC_SYSC_NANOSLEEP' ?
Dies sieht mit nicht nach einen C-Header aus, ansonsten würde da nicht "FPC_.xxx" stehen. Gefunden in der "bunxh.inc"
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Verschiedene "external"

Beitrag von theo »

Mathias hat geschrieben:
So 27. Nov 2022, 13:50
Was bedeutet das "name" ?
Und was ist das 'FPC_SYSC_NANOSLEEP' ?
Das ist der Name der Funktion in der externen Lib.
https://www.freepascal.org/docs-html/ref/refse98.html

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Verschiedene "external"

Beitrag von Winni »

Hi!

Nicht raten, sondern lesen:
https://www.freepascal.org/docs-html/3 ... su148.html

Winni

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Verschiedene "external"

Beitrag von Mathias »

Winni hat geschrieben:
So 27. Nov 2022, 14:30
Hi!

Nicht raten, sondern lesen:
https://www.freepascal.org/docs-html/3 ... su148.html

Winni
Wen ich das richtig verstanden habe, heisst der richtige Namen in der Bibliotheke 'FPC_SYSC_NANOSLEEP' ?
Aber das kann kaum eine Bibliothek von /usr/include sein, sonst würde nicht FPC_xxx stehen.

Code: Alles auswählen

Function  FpNanoSleep  (req : ptimespec;rem : ptimespec):cint; external name 'FPC_SYSC_NANOSLEEP';
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Verschiedene "external"

Beitrag von Winni »

Mathias hat geschrieben:
So 27. Nov 2022, 17:29
Aber das kann kaum eine Bibliothek von /usr/include sein, sonst würde nicht FPC_xxx stehen.
Wer hat das denn behauptet ?

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Verschiedene "external"

Beitrag von PascalDragon »

Mathias hat geschrieben:
So 27. Nov 2022, 13:50
So eine external Deklaration leuchtet mir ein, da wird die Funktion in den *.h im Ordner "X11" gesucht.

Code: Alles auswählen

function XOpenDisplay(para1:Pchar):PDisplay;cdecl;external 'X11';
Falsch. Das weist den Linker an das Symbol XOpenDisplay (bzw. _XOpenDisplay je nach Plattform) in der Bibliothek libX11.so (im Fall vom Linux) zu suchen. C Header sind in keinem Fall involviert.
Mathias hat geschrieben:
So 27. Nov 2022, 13:50
Jetzt habe ich sowas enrdeckt:

Code: Alles auswählen

    Function  FpNanoSleep  (req : ptimespec;rem : ptimespec):cint; external name 'FPC_SYSC_NANOSLEEP';
Was bedeutet das "name" ?
Und was ist das 'FPC_SYSC_NANOSLEEP' ?
Dies sieht mit nicht nach einen C-Header aus, ansonsten würde da nicht "FPC_.xxx" stehen. Gefunden in der "bunxh.inc"
external name <IDENTIFIER> weist den Linker an nach dem Symbol <IDENTIFIER> in den Objektdateien des Programms (also die Kompilate der Quelldateien und der RTL) bzw. in den eingebundenen Bibliotheken (durch {$L <libname>}) zu suchen.

external <LIBNAME> name <IDENTIFIER> kombiniert dann beide: der Linker wird angewiesen das Symbol <IDENTIFIER> in der Bibliothek (unter Linux) lib<LIBNAME>.so zu suchen.
FPC Compiler Entwickler

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Verschiedene "external"

Beitrag von Mathias »

Falsch. Das weist den Linker an das Symbol XOpenDisplay (bzw. _XOpenDisplay je nach Plattform) in der Bibliothek libX11.so (im Fall vom Linux) zu suchen. C Header sind in keinem Fall involviert.
Verstehe ich das jetzt richtig, sämtliche libs befinden sich im Ordner /usr/lib/x86_64-linux-gnu.
Und bei external schreibt man die Lib rein, ohne das lib und .so. Im Beispiele von von X11 so libX11.so ?
Und im Ordner /usr/include befinden sich die Header, welche ober nur der C/C++-Programmierer braucht ?


Und die external mit "name", kann man auf x-beliebige *.so anwenden ?
Auch solche, welche in Pascal kompiliert wurden ?
Also solche, welche man in Lazarus unter Project/Projecteinstellungen/Compilereinstellungen/Pfade/Bilbiotheken eingibt ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Verschiedene "external"

Beitrag von Socke »

Mathias hat geschrieben:
Mo 28. Nov 2022, 17:54
Verstehe ich das jetzt richtig, sämtliche libs befinden sich im Ordner /usr/lib/x86_64-linux-gnu.
Ein eindeutiges Jein. Dort liegen insbesondere dynamisch zur Laufzeit geladenen Bibliotheken. Bibliotheken, die statisch in das Progamm hineingelinkt werden, können prinzipiell auch woanders liegen - wozu auch die ganzen kompilierten Pascal-Units gehören.
Mathias hat geschrieben:
Mo 28. Nov 2022, 17:54
Und bei external schreibt man die Lib rein, ohne das lib und .so. Im Beispiele von von X11 so libX11.so ?
Da gibt es ein wenig Magie durch den FPC. Eine genaue Dokumentation habe ich nicht gefunden, im Programmer's Guide ist es aber angeschnitten. Durch die Magie kannst du theoretisch nut 'X11' schreiben und unter verschiedenen Betriebssystemen wird entsprechend der Konvention der richtige Name gebildet. Häufig wird aber auch je nach Betriebssystem der vollständige Name angegeben.
Mathias hat geschrieben:
Mo 28. Nov 2022, 17:54
Und im Ordner /usr/include befinden sich die Header, welche ober nur der C/C++-Programmierer braucht ?
Richtig. Unter Pascal brauchst du eigene Units, in denen die Funktionen der Bibliothek deklariert sind. In dieser Hinsicht übernehmen sie die Funktion der Header-Dateien. Da aber jeder Compiler nur eine Sprache versteht, braucht es für Pascal und C/C++ unterschiedliche Dateien.

Mathias hat geschrieben:
Mo 28. Nov 2022, 17:54
Und die external mit "name", kann man auf x-beliebige *.so anwenden ?
Auch solche, welche in Pascal kompiliert wurden ?
Also solche, welche man in Lazarus unter Project/Projecteinstellungen/Compilereinstellungen/Pfade/Bilbiotheken eingibt ?
Ja, das geht.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Verschiedene "external"

Beitrag von Mathias »

Ich habe folgendes probiert:

Code: Alles auswählen

$ grep FPC_SYSC_NANOSLEEP -i -I -R
fpcsrc/rtl/unix/bunxh.inc:    Function  FpNanoSleep  (req : ptimespec;rem : ptimespec):cint; external name 'FPC_SYSC_NANOSLEEP';
fpcsrc/rtl/bsd/ossysc.inc:Function FpNanoSleep(req : ptimespec;rem : ptimespec) : cint; [public, alias : 'FPC_SYSC_NANOSLEEP'];
fpcsrc/rtl/linux/ossysc.inc:Function FpNanoSleep(req : ptimespec;rem : ptimespec):cint; [public, alias : 'FPC_SYSC_NANOSLEEP'];
fpcsrc/rtl/beos/ossysc.inc:Function FpNanoSleep(req : ptimespec;rem : ptimespec) : cint; [public, alias : 'FPC_SYSC_NANOSLEEP'];
grep: lazarus/components/chmhelp/lhelp/lhelp.app/Contents/MacOS/lhelp: Datei oder Verzeichnis nicht gefunden
Müsste da nicht irgendwo eine Funktion mit dem der Bezeichnung 'FPC_SYSC_NANOSLEEP' auffindbar sein ?
Da gibt es ein wenig Magie durch den FPC. Eine genaue Dokumentation habe ich nicht gefunden, im Programmer's Guide ist es aber angeschnitten. Durch die Magie kannst du theoretisch nut 'X11' schreiben und unter verschiedenen Betriebssystemen wird entsprechend der Konvention der richtige Name gebildet. Häufig wird aber auch je nach Betriebssystem der vollständige Name angegeben.
Dies konnte ich jetzt nachvollziehen

Code: Alles auswählen

function XOpenDisplay(para1:Pchar):PDisplay; cdecl; external 'X11';  // geht
function XOpenDisplay(para1:Pchar):PDisplay; cdecl; external 'libX11.so';  // geht
function XOpenDisplay(para1:Pchar):PDisplay; cdecl; external 'libX11';  // geht
function XOpenDisplay(para1:Pchar):PDisplay; cdecl; external 'X11.so';  // geht
function XOpenDisplay(para1:Pchar):PDisplay; cdecl; external 'blabla';  // geht nicht
Und wen ich selbst eine Bibliothek, welche in C/C++ lesbar ist, müsste ich es so machen ?

Code: Alles auswählen

library Project1;

  function Test(x, y: integer): integer;
  begin
    Result := x + y;
  end;

begin
end.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Verschiedene "external"

Beitrag von Socke »

Mathias hat geschrieben:
Di 29. Nov 2022, 14:08
Ich habe folgendes probiert:

Code: Alles auswählen

$ grep FPC_SYSC_NANOSLEEP -i -I -R
fpcsrc/rtl/unix/bunxh.inc:    Function  FpNanoSleep  (req : ptimespec;rem : ptimespec):cint; external name 'FPC_SYSC_NANOSLEEP';
fpcsrc/rtl/bsd/ossysc.inc:Function FpNanoSleep(req : ptimespec;rem : ptimespec) : cint; [public, alias : 'FPC_SYSC_NANOSLEEP'];
fpcsrc/rtl/linux/ossysc.inc:Function FpNanoSleep(req : ptimespec;rem : ptimespec):cint; [public, alias : 'FPC_SYSC_NANOSLEEP'];
fpcsrc/rtl/beos/ossysc.inc:Function FpNanoSleep(req : ptimespec;rem : ptimespec) : cint; [public, alias : 'FPC_SYSC_NANOSLEEP'];
grep: lazarus/components/chmhelp/lhelp/lhelp.app/Contents/MacOS/lhelp: Datei oder Verzeichnis nicht gefunden
Müsste da nicht irgendwo eine Funktion mit dem der Bezeichnung 'FPC_SYSC_NANOSLEEP' auffindbar sein ?
Du hast doch welche gefunden! über alias : 'FPC_SYSC_NANAOSLEEP' wird ein zusätzlicher Name definiert, unter dem der Linker diese Funktion finden kann.
Mathias hat geschrieben:
Di 29. Nov 2022, 14:08
Und wen ich selbst eine Bibliothek, welche in C/C++ lesbar ist, müsste ich es so machen ?
Schau dir mal den Programmer's Guide an, da ist das beschrieben: https://www.freepascal.org/docs-html/pr ... gse55.html
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Verschiedene "external"

Beitrag von PascalDragon »

Mathias hat geschrieben:
Mo 28. Nov 2022, 17:54
Falsch. Das weist den Linker an das Symbol XOpenDisplay (bzw. _XOpenDisplay je nach Plattform) in der Bibliothek libX11.so (im Fall vom Linux) zu suchen. C Header sind in keinem Fall involviert.
Verstehe ich das jetzt richtig, sämtliche libs befinden sich im Ordner /usr/lib/x86_64-linux-gnu.
Wie Socke geschrieben hat, können die Bibliotheken prinzpiell an beliebigen Orten liegen. Solange sie in den Verzeichnissen in $PATH oder $LD_LIBRARY_PATH zu finden sind, können sie auch einfach vom Linker gefunden werden, ansonsten muss man die Verzeichnisse beim Kompilieren mit angeben.
Mathias hat geschrieben:
Mo 28. Nov 2022, 17:54
Und bei external schreibt man die Lib rein, ohne das lib und .so. Im Beispiele von von X11 so libX11.so ?
Und im Ordner /usr/include befinden sich die Header, welche ober nur der C/C++-Programmierer braucht ?
Korrekt.
Mathias hat geschrieben:
Mo 28. Nov 2022, 17:54
Und die external mit "name", kann man auf x-beliebige *.so anwenden ?
Auch solche, welche in Pascal kompiliert wurden ?
Ja. Und auch für DLLs unter Windows und DYLIBs unter macOS.
Mathias hat geschrieben:
Mo 28. Nov 2022, 17:54
Also solche, welche man in Lazarus unter Project/Projecteinstellungen/Compilereinstellungen/Pfade/Bilbiotheken eingibt ?
Das ist genau der Pfad, den ich oben meine.
Mathias hat geschrieben:
Di 29. Nov 2022, 14:08
Ich habe folgendes probiert:

Code: Alles auswählen

$ grep FPC_SYSC_NANOSLEEP -i -I -R
fpcsrc/rtl/unix/bunxh.inc:    Function  FpNanoSleep  (req : ptimespec;rem : ptimespec):cint; external name 'FPC_SYSC_NANOSLEEP';
fpcsrc/rtl/bsd/ossysc.inc:Function FpNanoSleep(req : ptimespec;rem : ptimespec) : cint; [public, alias : 'FPC_SYSC_NANOSLEEP'];
fpcsrc/rtl/linux/ossysc.inc:Function FpNanoSleep(req : ptimespec;rem : ptimespec):cint; [public, alias : 'FPC_SYSC_NANOSLEEP'];
fpcsrc/rtl/beos/ossysc.inc:Function FpNanoSleep(req : ptimespec;rem : ptimespec) : cint; [public, alias : 'FPC_SYSC_NANOSLEEP'];
grep: lazarus/components/chmhelp/lhelp/lhelp.app/Contents/MacOS/lhelp: Datei oder Verzeichnis nicht gefunden
Müsste da nicht irgendwo eine Funktion mit dem der Bezeichnung 'FPC_SYSC_NANOSLEEP' auffindbar sein ?
Wie Socke geschrieben hat: ist doch da.
Mathias hat geschrieben:
Di 29. Nov 2022, 14:08
Und wen ich selbst eine Bibliothek, welche in C/C++ lesbar ist, müsste ich es so machen ?

Code: Alles auswählen

library Project1;

  function Test(x, y: integer): integer;
  begin
    Result := x + y;
  end;

begin
end.
Lies dir Mal ein paar Tutorials zum Schreiben von Bibliotheken in FPC oder Delphi durch. Die wichtigsten Punkte sind, dass du deine Funktionen auch exportieren musst (Stichwort exports-Abschnitt) und du musst die richtige Aufrufkonvention verwenden (besonders wichtig auf i386-Plattformen, da es dort einen ziemlichen Zoo gibt). Der Standard für C/C++ ist hierbei cdecl.
FPC Compiler Entwickler

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Verschiedene "external"

Beitrag von Mathias »

Ich stehe wieder mal mit "external" an.
Ich habe erfolgreich in C die lib "v4l2_driver.o" erstellt. Dies habe ich dann in mein Lazarus Project-Verzeichniss kopiert.
Diese wollte ich in Lazarus einbinden.

Code: Alles auswählen

program project1;
  {$L v4l2_driver.o}

function v4l2_open(device: PChar): longint; cdecl; external;

var
  video_files: longint;
begin
  video_files := v4l2_open('/dev/null');
end.   
Nur motzt er da mit folgendem Fehler: "project1.lpr(10,1) Error: Error while linking"
Auch wen ich es so mache, der gleiche Fehler.

Code: Alles auswählen

program project1;

function v4l2_open(device: PChar): longint; cdecl; external 'v4l2_driver.o';
  
begin
end.     
Binde ich aber eine lib von /usr/bin ein, als Beispiel printf, geht es problemlos.

Code: Alles auswählen

program project1;

  procedure printf(c:pchar); varargs cdecl; external 'c';
  
begin
  printf('Hello World %i\n', 1234);
end.
Was mache ich falsch ?
Irgendwie sollte es doch auch möglich sein, eine *.o einzubinden, wen sie lokal verwendet wird.

Hier habe ich schon geguckt: https://lazarus-ccr.sourceforge.io/fpcd ... su147.html
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6164
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Verschiedene "external"

Beitrag von Mathias »

Jetzt hat es mit rumbasteln geklappt.

Code: Alles auswählen

program project1;

  {$L v4l2_driver.o}
  {$LinkLib c}

  function v4l2_open(device: PChar): longint; cdecl; external;

const
  device = '/dev/video0';
var
  video_files: longint;
begin
  video_files := v4l2_open(device);
  if video_files = -1 then begin
    WriteLn('Kann Gerät "', device, '" nicht öffnen');
  end;
end. 
Anscheinend muss noch auf die libc verlinkt werden.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Verschiedene "external"

Beitrag von af0815 »

Brauchst du Sachen aus V4L, dann schau dir die Umsetzung an. Ich habe eine Version bei mir liegen https://github.com/afriess/fpcVideo4L2 . Das ist unter andern von hier https://github.com/LongDirtyAnimAlf/ZXing.Delphi extrahiert.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Verschiedene "external"

Beitrag von PascalDragon »

Mathias hat geschrieben:
Mo 26. Jun 2023, 18:13
Was mache ich falsch ?
Irgendwie sollte es doch auch möglich sein, eine *.o einzubinden, wen sie lokal verwendet wird.
Die external <name> Direktive ist nur für dynamische Bibliotheken (.dll, .so and .dylib) gedacht und nicht für statische Bibliotheken (.lib und .a) oder Objektdateien (.obj oder .o). Für die letzteren darfst du nur external allein verwenden (oder external name <name>, wenn du den Namen des Symbols anpassen musst). Die eigentliche Datei linkst du dann mit {$link <datei>} dazu. Und wie du festgestellt hast benötigt die Objektdatei (oder statische Bibliothek) dann eventuell noch die C Bibliothek.

Wobei ich schon gar nicht verstehe, warum du libv4l2 statisch dazu linkst und nicht einfach dynamisch wie es zum Beispiel der Code von af0815 macht... 🤔
FPC Compiler Entwickler

Antworten