in C programmierte Bibliothek einbinden
in C programmierte Bibliothek einbinden
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
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
Also so?
Genau wie eine DLL unter Windows?
Code: Alles auswählen
interface
function addiere(zahl1, zahl2: integer): integer; stdcall;
implementation
function addiere(zahl1, zahl2: integer): integer; stdcall;
external 'librechnen.so';
Leider klappt es noch immer nicht.
Müsste nicht die Funktion in C so aussehen?
Allerdings sagt dann der C-Compiler:
Genau dasselbe passiert bei "_cdecl" statt "_stdcall".
Wenn ich "_stdcall" weglasse, kann ich mit
die *.so erzeugen.
Will ich die allerdings wie oben beschrieben mit dem Lazarus-Programm aufrufen, kommt beim Kompilieren die Meldung:
Was mache ich falsch?
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);
}
Code: Alles auswählen
main.c:12: Fehler: expected »=«, »,«, »;«, »asm« or »__attribute__« before »addiere«
Wenn ich "_stdcall" weglasse, kann ich mit
Code: Alles auswählen
gcc -shared -o librechnen.so main.c
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"
-
- 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)
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 ?
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
Michael Springwald
Wieso "TForm1.addiere"? Zeig mal den Code. Addiere sollte ja keine Methode von TForm1 sein oder?zummy hat geschrieben:Was mache ich falsch?Code: Alles auswählen
unit1.pas(36,14) Error: Forward declaration not solved "TForm1.addiere(LongInt, LongInt):LongInt"
Unter GCC Linux ist es glaubs cdecl.Christian hat geschrieben:int addiere(int zahl1, int zahl2);
{
HIER STEHT WAS
return(IRGENDEINENWERT);
}
sollte bereits als stdcall deklariert sein
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;
}
-
- 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
Wegen der Cross-Kiste sollte man vielleicht:
nutzen. Dann braucht man nur neu kompilieren.
Code: Alles auswählen
const
{$IFDEF UNIX} extmathtlib = 'rechnen.so'; {$ENDIF}
{$IFDEF WINDOWS} extmathtlib = 'rechnen.dll'; {$ENDIF}
function addiere(args): longint; cdecl; external extmathlib;
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.
(Ringelnatz)
(Ringelnatz)
Nö, "rechnen" reicht (siehe Oben). Das wird dann ausgewertet zu librechnen.so bzw. rechnen.dll.schnullerbacke hat geschrieben:Wegen der Cross-Kiste sollte man vielleicht:
nutzen. Dann braucht man nur neu kompilieren.Code: Alles auswählen
const {$IFDEF UNIX} extmathtlib = 'rechnen.so'; {$ENDIF} {$IFDEF WINDOWS} extmathtlib = 'rechnen.dll'; {$ENDIF} function addiere(args): longint; cdecl; external extmathlib;
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
-
- 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
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...
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...

Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.
(Ringelnatz)
(Ringelnatz)
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:
Die C-Datei sieht so aus:
Ich erstelle die Datei libmandel.so mit dem Befehl:
Die libmandel.so liegt im selben Verzeichnis wie das Lazarus-Programm.
Wenn ich jetzt mit Lazarus kompiliere, erscheint lediglich die Meldung "Ausführung angehalten."
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.
Code: Alles auswählen
#include <stdio.h>
#include <math.h>
int iteration(long double rec, long double imc, int iter)
{
//HIER DER GANZE KRAM
}
Code: Alles auswählen
gcc -shared -o libmandel.so main.c
Wenn ich jetzt mit Lazarus kompiliere, erscheint lediglich die Meldung "Ausführung angehalten."