Hallo an Alle,
ich bin gerade dabei, mir FPC genauer anzusehen
und habe eine Frage zur Einbindung von Funktionen aus einer DLL.
Ich habe es mitlerweile geschafft Funktionen einer DLL in Freepascal zu verwenden,
aber bei der Deklaration der Funktion muss der Name der Funktion 'name 'TESTSTRING';'
case sensitive geschrieben werden.
Function TestString(x : PChar):PChar; stdcall; external 'Environ.DLL' name 'TESTSTRING';
Würde ich 'name 'teststring';' schreiben, wird der Einsprungpunkt nicht gefunden.
Das bedeutet aber, ich muss bei jede Funktion mit dem Dependensy Walker nachschauen wie
sie in der DLL vorliegt.
Gibt es da eine Einstellung oder Schalter, dass ich nicht machen muss?
FPC Version 2.7.1
CodeTyphon 4.3
Danke für eure Hilfe
DLL Funktion statisch binden
-
- Beiträge: 129
- Registriert: Sa 25. Mai 2013, 07:43
- OS, Lazarus, FPC: Win7_x64 (FPC:4.7.1)
- CPU-Target: 32Bit
DLL Funktion statisch binden
Vbxler
-------------------------
-------------------------
- m.fuchs
- Lazarusforum e. V.
- Beiträge: 2822
- Registriert: Fr 22. Sep 2006, 19:32
- OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
- CPU-Target: x86, x64, arm
- Wohnort: Berlin
- Kontaktdaten:
Re: DLL Funktion statisch binden
Nein, da andere Sprachen durchaus Case-sensitive sind. Es könnte vorkommen, dass eine DLL zwei gleiche Namen nur mit unterschiedlicher Groß-/Kleinschreibung hat.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
-
- Lazarusforum e. V.
- Beiträge: 3178
- 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: DLL Funktion dynamisch binden
Leider gibt es einen Unterschied zwischen dem, was im Thread-Titel steht und was du mit deinem Beispiel-Code zeigst. Daher noch ein kurze Erklärung am Rande: Statisch heißt unveränderbar, dynamisch heißt veränderbar. Daher gibt es 3 Möglichkeiten eine Funktion in ein Programm einzubinden.Vbxler hat geschrieben:und habe eine Frage zur Einbindung von Funktionen aus einer DLL.
- Statisch Die Bibliothekt wird beim Übersetzen des Programms in diese fest integriert. Es gibt am Ende nur eine Programmdatei.
- Dynamisch, frühe Bindung (early binding) Programm und Bibltiothek werden getrennt übersetzt; es gibt also eine Programmdatei und eine Bibliotheksdatei. In der Programmdatei ist hinterlegt, welche Funktionen sie nutzen will (ggf. mit Bibliotheksname). Beim Starten des Programms wird die Bibltiothek automatisch vom Betriebssystem geladen und in das Programm (im Speicher!) gelinkt.
- Dynamisch, späte Bindung (late binding) Programm und Bibltiothek werden getrennt übersetzt; es gibt also eine Programmdatei und eine Bibliotheksdatei. Das Programm ruft entsprechende Betriebssystem-Funktionen auf, mit denen es mitteilt, dass eine Bibliothek geladen werden soll. Sobald diese geladen ist, sucht das Programm nach den Startadressen der gewünschten Funktionen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
-
- Beiträge: 129
- Registriert: Sa 25. Mai 2013, 07:43
- OS, Lazarus, FPC: Win7_x64 (FPC:4.7.1)
- CPU-Target: 32Bit
Re: DLL Funktion statisch binden
ja, du hast vermutlich recht, ich führe eine dynamisch, frühe Bindung durch mit:
Function TestString(x : PChar):PChar; stdcall; external 'Environ.DLL' name 'TESTSTRING';
Latebinding wäre ja mit LoadLibrary....
Function TestString(x : PChar):PChar; stdcall; external 'Environ.DLL' name 'TESTSTRING';
Latebinding wäre ja mit LoadLibrary....
Vbxler
-------------------------
-------------------------
-
- Beiträge: 199
- Registriert: Di 20. Okt 2015, 23:13
Re: DLL Funktion statisch binden
Wie sähe das bei statischer Bindung aus, also bei Einbindung der Bibliothek in die Exe. Das Programm soll dann aus einer .exe bestehen, die den Code der Bibliothek statisch enthält.
Wie muss ich so eine Bibliothek einbinden? Im Gegensatz zur .dll, die dynamisch eingebunden wird und dann mit dem Programm verteilt werden muss. Ich will die Bibliothek statisch in den Code einbinden und dann nur die Exe verteilen.
Wie muss ich so eine Bibliothek einbinden? Im Gegensatz zur .dll, die dynamisch eingebunden wird und dann mit dem Programm verteilt werden muss. Ich will die Bibliothek statisch in den Code einbinden und dann nur die Exe verteilen.
Re: DLL Funktion statisch binden
Wie eine DLL nur im Speicher aus der Resource heraus genutzt wird, habe ich noch nicht recherchiert. Allerdings habe ich die Möglichkeit eine DLL als Resource einzubinden, zum Programmstart zu extrahieren und beim Aufräumen wieder zu entfernen getestet, was hier auch gut funktioniert hat (Windows 7).
Infos dazu: http://wiki.freepascal.org/Lazarus_Resources
Beispiel für Lazarus 32bit unter Windows mit sqlite3.dll (Packages SQLDBLaz muss dafür installiert sein) anbei.
PS: Ob es ein gutes Vorgehen ist, eine DLL in die Executable zu packen, steht auf einem anderen Blatt. Dadurch erhöht sich die Größe der Datei und Virenscanner können Alarm auslösen (was vom User garantiert nicht gern gesehen wird).
Infos dazu: http://wiki.freepascal.org/Lazarus_Resources
Beispiel für Lazarus 32bit unter Windows mit sqlite3.dll (Packages SQLDBLaz muss dafür installiert sein) anbei.
PS: Ob es ein gutes Vorgehen ist, eine DLL in die Executable zu packen, steht auf einem anderen Blatt. Dadurch erhöht sich die Größe der Datei und Virenscanner können Alarm auslösen (was vom User garantiert nicht gern gesehen wird).
Code: Alles auswählen
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Forms, DBGrids, LResources, Classes, sysutils, db,
sqlite3conn, sqldb;
type
{ TForm1 }
TForm1 = class(TForm)
Datasource1: TDataSource;
DBGrid1: TDBGrid;
SQLite3Connection1: TSQLite3Connection;
SQLQuery1: TSQLQuery;
SQLTransaction1: TSQLTransaction;
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
SQLiteFile: string;
DatabaseFile: string;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
procedure CreateFile(aFileName, aResourceName: string);
var
F: TFileStream;
r: TLResource;
begin
r := LazarusResources.Find(aResourceName);
if not Assigned(r) then
raise Exception.Create('Resource ' + aResourceName + ' is missing');
F := TFileStream.Create(aFileName, fmCreate);
try
F.Write(r.Value[1], Length(r.Value));
finally
F.Free;
end;
end;
begin
SQLiteFile := ExtractFilePath(ParamStr(0)) + 'sqlite3.dll';
DatabaseFile := ExtractFilePath(ParamStr(0)) + 'test.db';
CreateFile(SQLiteFile, 'sqlite3');
CreateFile(DatabaseFile, 'test');
SQLite3Connection1.Connected := True;
SQLQuery1.SQL.Text:='SELECT name, nachname FROM personen;';
SQLQuery1.Open;
end;
initialization
{$I project1.lrs}
finalization;
if FileExists(SQLiteFile) then DeleteFile(SQLiteFile);
if FileExists(DatabaseFile) then DeleteFile(DatabaseFile);
end.
- Dateianhänge
-
TestResource.zip
- (464.08 KiB) 81-mal heruntergeladen
Code: Alles auswählen
type
TLiveSelection = (lsMoney, lsChilds, lsTime);
TLive = Array[0..1] of TLiveSelection;