DLL Funktion statisch binden

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Vbxler
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

Beitrag von Vbxler »

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
Vbxler
-------------------------

Benutzeravatar
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

Beitrag von m.fuchs »

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

Socke
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

Beitrag von Socke »

Vbxler hat geschrieben:und habe eine Frage zur Einbindung von Funktionen aus einer DLL.
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.
  • 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

Vbxler
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

Beitrag von Vbxler »

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....
Vbxler
-------------------------

fpGUIcoder
Beiträge: 199
Registriert: Di 20. Okt 2015, 23:13

Re: DLL Funktion statisch binden

Beitrag von fpGUIcoder »

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.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: DLL Funktion statisch binden

Beitrag von Michl »

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).

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;  

Antworten