in C programmierte Bibliothek einbinden

zummy
Beiträge: 17
Registriert: Mo 6. Nov 2006, 14:00

in C programmierte Bibliothek einbinden

Beitrag von zummy »

Hallo,

kann mir jemand erklären, wie ich in mein Lazarus-Programm eine in C programmierte Bibliothek einbinde?

Ich möchte, dass einer Funktion in der Bibliothek Parameter mitgegeben werden und ich ein Ergebnis zurückerhalte.

Danke schonmal
zummy

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Genauso wie eine in Pascal programmierte Bibliothek.
Solang sie wirklich in C programmiert ist...
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

zummy
Beiträge: 17
Registriert: Mo 6. Nov 2006, 14:00

Beitrag von zummy »

Also so?

Code: Alles auswählen

interface
  function addiere(zahl1, zahl2: integer): integer; stdcall;
 
implementation
 
function addiere(zahl1, zahl2: integer): integer; stdcall;
external 'librechnen.so';
Genau wie eine DLL unter Windows?

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

jenau
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

zummy
Beiträge: 17
Registriert: Mo 6. Nov 2006, 14:00

Beitrag von zummy »

Leider klappt es noch immer nicht.


Müsste nicht die Funktion in C so aussehen?

Code: Alles auswählen

#include <stdio.h>
#include <math.h>
 
int main(void)
{	
}
 
int _stdcall addiere(int zahl1, int zahl2) 
{
  HIER STEHT WAS	
  return(IRGENDEINENWERT);	
}
Allerdings sagt dann der C-Compiler:

Code: Alles auswählen

main.c:12: Fehler: expected »=«, »,«, »;«, »asm« or »__attribute__« before »addiere«
Genau dasselbe passiert bei "_cdecl" statt "_stdcall".

Wenn ich "_stdcall" weglasse, kann ich mit

Code: Alles auswählen

gcc -shared -o librechnen.so main.c
die *.so erzeugen.

Will ich die allerdings wie oben beschrieben mit dem Lazarus-Programm aufrufen, kommt beim Kompilieren die Meldung:

Code: Alles auswählen

unit1.pas(36,14) Error: Forward declaration not solved "TForm1.addiere(LongInt, LongInt):LongInt"
Was mache ich falsch?

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

Ich würde sagen, du brauchst erstmal die DLL, fertig.

Dann schreibst du dir einen Header. Genau weiß ich es leider nicht, weil ich mich mit DLL selten befasst habe. Aber ich glaube so ist die Vorgehensweise.

Im Moment sieht es so aus, als ob du Probleme hast die DLL zu erzeugen.
Sehe ich das richtig ?
MFG
Michael Springwald

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

Beitrag von theo »

zummy hat geschrieben:

Code: Alles auswählen

unit1.pas(36,14) Error: Forward declaration not solved "TForm1.addiere(LongInt, LongInt):LongInt"
Was mache ich falsch?
Wieso "TForm1.addiere"? Zeig mal den Code. Addiere sollte ja keine Methode von TForm1 sein oder?

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

int addiere(int zahl1, int zahl2);
{
HIER STEHT WAS
return(IRGENDEINENWERT);
}

sollte bereits als stdcall deklariert sein
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

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

Beitrag von theo »

Christian hat geschrieben:int addiere(int zahl1, int zahl2);
{
HIER STEHT WAS
return(IRGENDEINENWERT);
}

sollte bereits als stdcall deklariert sein
Unter GCC Linux ist es glaubs cdecl.

Hab's mal eben probiert. So geht's bei mir:

Code: Alles auswählen

function addiere(zahl1, zahl2: LongInt): LongInt; cdecl; external 'rechnen';
 
{ TForm1 }
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  Caption:=Inttostr(addiere(1,2));
end;

Wobei:

Code: Alles auswählen

#include <stdio.h>
#include <math.h>
 
 
int addiere(int zahl1, int zahl2)
{
    return zahl1+zahl2;
}

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

Wegen der Cross-Kiste sollte man vielleicht:

Code: Alles auswählen

const
  {$IFDEF UNIX} extmathtlib = 'rechnen.so'; {$ENDIF}
  {$IFDEF WINDOWS} extmathtlib = 'rechnen.dll'; {$ENDIF}
 
function addiere(args): longint; cdecl; external extmathlib;
nutzen. Dann braucht man nur neu kompilieren.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

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

Beitrag von theo »

schnullerbacke hat geschrieben:Wegen der Cross-Kiste sollte man vielleicht:

Code: Alles auswählen

const
  {$IFDEF UNIX} extmathtlib = 'rechnen.so'; {$ENDIF}
  {$IFDEF WINDOWS} extmathtlib = 'rechnen.dll'; {$ENDIF}
 
function addiere(args): longint; cdecl; external extmathlib;
nutzen. Dann braucht man nur neu kompilieren.
Nö, "rechnen" reicht (siehe Oben). Das wird dann ausgewertet zu librechnen.so bzw. rechnen.dll.
Darum braucht man sich nicht kümmern.

Aber vielleicht eher {$IFDEF UNIX} cdecl;{$ENDIF} {$IFDEF WINDOWS} stdcall; {$ENDIF}
Das entspräche dann afaik dem jeweiligen Standard. Wenn man aber die C Library auch selber schreibt, kann man das wohl auch dort regeln

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Beitrag von monta »

Ich bin mir nicht sicher, aber ist der Windows-Standard nicht auch cdecl, wenn nicht explizit angegeben?

Bzw. ist das ganze nicht grundsätzlich vom C-Compiler und dessen Einstellung abhängig?
Johannes

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

Beitrag von theo »

Wahrscheinlich schon. Ich weiss nur, dass man die Winapi Funktionen meist mit stdcall aufruft und unter Linux für Library Funktionen fast immer cdecl benötigt

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

Leider ist das bei Windoof's alles anders, da folgen viele Sachen der Pascal-Aufrufkonvention. Da muß man dann zwingend stdcall angeben.

Nur wenn du eine C/C++ lib einbindest muß auch cdecl angegeben werden, das ist wegen der Pointer auf Result bei Funktionen oder Pointern als var-Parameter nötig, damit der Speicher richtig freigegeben wird.

Trotzdem würde ich die Librarys immer als const setzen. Das läßt sich dann leichter ändern... :wink:
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

zummy
Beiträge: 17
Registriert: Mo 6. Nov 2006, 14:00

Beitrag von zummy »

Danke für die vielen Antworten!

Der erste Fehler war, dass die Funktion im Interface-Teil unter type TForm1 deklariert war. Das ist jetzt behoben.

Der Code sieht jetzt so aus (Bezeichnungen haben sich etwas geändert, es geht um die Funktion iteration:

Code: Alles auswählen

unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, Buttons,
  StdCtrls, ExtCtrls,Math, Spin;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
  //...HIER DIE KOMPONENTEN UND PROZEDUREN...
 
  private
    { private declarations }
  public
    { public declarations }
  end; 
 
function iteration(iter:integer; rec,imc:extended):integer; cdecl;
 
var
  Form1: TForm1; 
  bild: TPaintBox;
 
implementation
 
{ TForm1 }
 
function iteration(iter:integer; rec,imc:extended):integer; cdecl;
external 'libmandel.so';
 
procedure TForm1.Button1Click(Sender: TObject);
//...
//UND DIE GANZEN ANDEREN
//...
 
 
initialization
  {$I Unit1.lrs}
 
end.
Die C-Datei sieht so aus:

Code: Alles auswählen

#include <stdio.h>
#include <math.h>
 
int iteration(long double rec, long double imc, int iter) 
{
//HIER DER GANZE KRAM
}
Ich erstelle die Datei libmandel.so mit dem Befehl:

Code: Alles auswählen

gcc -shared -o libmandel.so main.c
Die libmandel.so liegt im selben Verzeichnis wie das Lazarus-Programm.

Wenn ich jetzt mit Lazarus kompiliere, erscheint lediglich die Meldung "Ausführung angehalten."

Antworten