AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen FreePascal DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinden?
Thema durchsuchen
Ansicht
Themen-Optionen

DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinden?

Ein Thema von Delphi-Laie · begonnen am 11. Mär 2010 · letzter Beitrag vom 1. Dez 2013
Antwort Antwort
Seite 2 von 6     12 34     Letzte »    
Benutzerbild von igel457
igel457

Registriert seit: 31. Aug 2005
1.622 Beiträge
 
FreePascal / Lazarus
 
#1

Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde

  Alt 12. Mär 2010, 13:47
Zitat:
Ich begreife zudem nicht, was dieses ganze Rumgemache mit Loadlibrary und GetProcAddress überhaupt soll. Bisher lernte ich in Delphi die Aufrufe externer DLL-Funktionen so kennen (hat bisher, bei mir jedenfalls, immer so geklappt), Beispiel:
Delphi-Quellcode:
interface

function OpenThread(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle; stdcall;

implementation

function OpenThread; external kernel32 name 'OpenThread';
Was spricht dagegen, dass auch mit FPC so zu machen? Diese Methode nennt sich statisches Laden

Und folgender Code von dir zum dynamischen Laden mit LoadLibrary ist ziemlicher Unsinn (siehe Kommentare):
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
  var
  DLLHandle,hProcessSnap: THandle;
  Beispielfunktion: function(dwFlags:Integer;th32ProcessID:Integer):THandle;//alternativ Funktionsergebnistyp:Pointer, mit dem klappt es aber auch nicht
begin
  DLLHandle := LoadLibrary(kernel32);
  if (DLLHandle < HINSTANCE_ERROR) then showmessage('DLL konnte nicht geladen werden!')
  else
    begin
    Beispielfunktion := @GetProcAddress(DLLHandle, 'CreateToolhelp32Snapshot'); //Du möchtest nicht mit dem Pointer auf GetProcAddress arbeiten
    //hProcessSnap:=CreateToolHelp32SnapShot(2{TH32CS_SNAPPROCESS},0);

    FreeLibrary(kernel32) //Du willst die Funktion doch noch verwenden, also darfst du die Bibliothek nicht entladen
    end
end;
Andreas
"Sollen sich auch alle schämen, die gedankenlos sich der Wunder der Wissenschaft und Technik bedienen, und nicht mehr davon geistig erfasst haben als die Kuh von der Botanik der Pflanzen, die sie mit Wohlbehagen frisst." - Albert Einstein
  Mit Zitat antworten Zitat
Nintendo

Registriert seit: 16. Feb 2009
82 Beiträge
 
#2

AW: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinden?

  Alt 1. Dez 2013, 11:38
Für den Fall das die Dll partout nicht geladen wird, habe ich die Idee, die Dll mit eigenen Routinen in den Ram zu laden, dann halt alle Relozierung selber zu erledigen und dann meinetwegen mit Assembler Call Befehlen die Funktionen der Dll aufzurufen.

Hier habe ich dazu einen anderen Thread eröffnet, der sich mit dem Problem unter Voraussetzung verschiedener Wortbreiten mit der Problematik beschäftigt:

http://www.delphipraxis.net/177781-l...ml#post1238082

Die Exporttabelle mit den anzusprechenden Funktionen wird, wie ich bisher verstanden habe durch eine Struktur mit Namen

IMAGE_EXPORT_DIRECTORY

repräsentiert. Ich kann aber die Adrees dieser Tabelle in den im Netz verfügbaren Dokus nirgends finden.


Delphi-Quellcode:
Delphi-Quellcode:
  PIMAGE_DOS_HEADER = ^IMAGE_DOS_HEADER;
  IMAGE_DOS_HEADER = record // DOS .EXE header
    e_magic : WORD; // Magic number { MZ for exe }
    e_cblp : WORD; // Bytes on last page of file
    e_cp : WORD; // Pages in file
    e_crlc : WORD; // Relocations
    e_cparhdr : WORD; // Size of header in paragraphs
    e_minalloc : WORD; // Minimum extra paragraphs needed
    e_maxalloc : WORD; // Maximum extra paragraphs needed
    e_ss : WORD; // Initial (relative) SS value
    e_sp : WORD; // Initial SP value
    e_csum : WORD; // Checksum
    e_ip : WORD; // Initial IP value
    e_cs : WORD; // Initial (relative) CS value
    e_lfarlc : WORD; // File address of relocation table
    e_ovno : WORD; // Overlay number
    e_res : array[0..3] of WORD; // Reserved words
    e_oemid : WORD; // OEM identifier (for e_oeminfo)
    e_oeminfo : WORD; // OEM information; e_oemid specific
    e_res2 : array[0..9] of WORD; // Reserved words
    e_lfanew : Longint; // File address of new exe header
  end;
 
  PIMAGE_FILE_HEADER = ^IMAGE_FILE_HEADER;
   IMAGE_FILE_HEADER = record
    Machine : WORD;
    NumberOfSections : WORD;
    TimeDateStamp : DWORD;
    PointerToSymbolTable : DWORD;
    NumberOfSymbols : DWORD;
    SizeOfOptionalHeader : WORD;
    Characteristics : WORD;
  end;

  TLocation = record
   case DWORD of
    0: (PhysicalAddress: DWORD);
    1: (VirtualSize: DWORD);
  end;

  IMAGE_SECTION_HEADER = record
    Name : array[0..IMAGE_SIZEOF_SHORT_NAME-1] of BYTE;
    Misc : TLocation;
    VirtualAddress : DWORD;
    SizeOfRawData : DWORD;
    PointerToRawData : DWORD;
    PointerToRelocations: DWORD;
    PointerToLinenumbers: DWORD;
    NumberOfRelocations : WORD;
    NumberOfLinenumbers : WORD;
    Characteristics : DWORD;
  end;

  PIMAGE_DATA_DIRECTORY = ^IMAGE_DATA_DIRECTORY;
   IMAGE_DATA_DIRECTORY = record
    VirtualAddress: DWORD;
    Size: DWORD;
  end;

  PIMAGE_BASE_RELOCATION = ^IMAGE_BASE_RELOCATION;
   IMAGE_BASE_RELOCATION = record
    VirtualAddress: DWORD;
    SizeOfBlock: DWORD;
  end;

  PIMAGE_OPTIONAL_HEADER32 = ^IMAGE_OPTIONAL_HEADER32;
   IMAGE_OPTIONAL_HEADER32 = record
    //
    // Standard fields.
    //

    Magic : WORD;
    MajorLinkerVersion : BYTE;
    MinorLinkerVersion : BYTE;
    SizeOfCode : DWORD;
    SizeOfInitializedData : DWORD;
    SizeOfUninitializedData : DWORD;
    AddressOfEntryPoint : DWORD;
    BaseOfCode : DWORD;
    BaseOfData : DWORD;

    //
    // NT additional fields.
    //

    ImageBase : DWORD;
    SectionAlignment : DWORD;
    FileAlignment : DWORD;
    MajorOperatingSystemVersion : WORD;
    MinorOperatingSystemVersion : WORD;
    MajorImageVersion : WORD;
    MinorImageVersion : WORD;
    MajorSubsystemVersion : WORD;
    MinorSubsystemVersion : WORD;
    Win32VersionValue : DWORD;
    SizeOfImage : DWORD;
    SizeOfHeaders : DWORD;
    CheckSum : DWORD;
    Subsystem : WORD;
    DllCharacteristics : WORD;
    SizeOfStackReserve : DWORD;
    SizeOfStackCommit : DWORD;
    SizeOfHeapReserve : DWORD;
    SizeOfHeapCommit : DWORD;
    LoaderFlags : DWORD;
    NumberOfRvaAndSizes : DWORD;
    DataDirectory : array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1] of IMAGE_DATA_DIRECTORY;
  end;

  PIMAGE_NT_HEADERS32 = ^IMAGE_NT_HEADERS32;
   IMAGE_NT_HEADERS32 = record
    Signature : DWORD;
    FileHeader : IMAGE_FILE_HEADER;
    OptionalHeader : IMAGE_OPTIONAL_HEADER32;
  end;
  
  TThunkCharacterisics = record
  case DWORD of
   0: (Characteristics : DWORD); { 0 for terminating null import descriptor        }
   1: (OriginalFirstThunk: DWORD); { RVA to original unbound IAT (PIMAGE_THUNK_DATA) }
  end;

  PIMAGE_IMPORT_DESCRIPTOR = ^IMAGE_IMPORT_DESCRIPTOR;
   IMAGE_IMPORT_DESCRIPTOR = record
    Thunk : TThunkCharacterisics;
    TimeDateStamp : DWORD; { 0 if not bound,                                }
                                            { -1 if bound, and real date\time stamp          }
                                            {     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) }
                                            { O.W. date/time stamp of DLL bound to (Old BIND)      }

    ForwarderChain : DWORD; { -1 if no forwarders                           }
    Name : DWORD;
    FirstThunk : DWORD; { RVA to IAT (if bound this IAT has actual addresses)  }
  end;
  
  TCode = record
  case LongWord of
   0 : (Offset,Segment: Word);
   1 : (LinearAddr: LongWord);
  end;
  
  PIMAGE_EXPORT_DIRECTORY = ^IMAGE_EXPORT_DIRECTORY;
   IMAGE_EXPORT_DIRECTORY = record
    Characteristics : DWORD;
    TimeDateStamp : DWORD;
    MajorVersion : WORD;
    MinorVersion : WORD;
    Name : DWORD;
    Base : DWORD;
    NumberOfFunctions : DWORD;
    NumberOfNames : PDWORD;
    AddressOfFunctions : PDWORD; { RVA from base of image }
    AddressOfNames : PDWORD; { RVA from base of image }
    AddressOfNameOrdinals : PDWORD; { RVA from base of image }
  end;
Ist vieleicht hier schon in einem Datenfeld die Adresse der Exporttabelle verborgen?

Die Struktur der .EXE Datei ist nur bis hierher dokumnentiert. Danach kommen die Section Header. Wo aber ist die Exporttabelle -> IMAGE_EXPORT_DIRECTORY?
  Mit Zitat antworten Zitat
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#3

Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde

  Alt 12. Mär 2010, 14:08
Danke auch für Deine Mühe!

Zitat von igel457:
Was spricht dagegen, dass auch mit FPC so zu machen? Diese Methode nennt sich statisches Laden
Na gut, statisch und dynamisch nahm ich auch schon irgendwo unterschwellig wahr. Edit: So, wie ich es von Delphi kenne (oben genannt, wohl die statische Variante), funktioniert es in Lazarus ja nicht, deshalb eben all' diese (bisher erfolglosen) Verrenkungen!

Zitat von igel457:
Du möchtest nicht mit dem Pointer auf GetProcAddress arbeiten
Dieser Kommentar verschließt sich mir leider völlig. Wieso möchte ich nicht mit dem Pointer auf GetProcAddress arbeiten?
Ich möchte einfach nur eine Funktion einer DLL benutzen. Diese muß ich anscheinend in der Weise extrahieren, daß ihre Funktionalität einer anderen Funktion übergeben wird, damit letztere (die neue, selbstdefinierte Funktion) die Funktionalität der ersteren übernimmt. Ich begreife nicht, warum das so kompliziert ist und der Lazarus/FP-Compiler sich so hartnäckig weigert. Sicher, irgendetwas stimmt nicht, doch was, weiß ich immer noch nicht.

Zitat von igel457:
Du willst die Funktion doch noch verwenden, also darfst du die Bibliothek nicht entladen
Daß nach dem Entladen die Funktionsbenutzung nicht mehr möglich ist, ist mir durchaus klar. Ich möchte die Funktion an jener Stelle überhaupt nicht mehr benutzen. Ich hätte ja schon einen Glückshormonausstoß, wenn das erfolgreich kompilieren und - optimalerweise - die Funktion sogar erfolgreich aufgerufen würde.
  Mit Zitat antworten Zitat
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#4

Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde

  Alt 12. Mär 2010, 14:28
Die ganze Kunst scheint darin zu bestehen, den Kommandozeilenschalter

{$mode DELPHI} zu verwenden, damit scheint es erstmal zu klappen.

Tausend Dank für die Geduld an alle! Problem (erstmal?) geklärt....
  Mit Zitat antworten Zitat
Benutzerbild von igel457
igel457

Registriert seit: 31. Aug 2005
1.622 Beiträge
 
FreePascal / Lazarus
 
#5

Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde

  Alt 12. Mär 2010, 15:21
"External" sollte auch ohne {$MODE DELPHI} funktionieren.

Schau dir mal die folgenden Header an, vielleicht helfen die dir:

OGG-Header (wird mit FPC mitgeliefert, statisches Laden):
http://audorra.svn.sourceforge.net/v...26&view=markup

Acinerella Header (von mir, statisches Laden):
http://audorra.svn.sourceforge.net/v...=1&view=markup

Libao Header (von mir, dynamisches Laden, AcGetProcAddress ist (fast) nur ein Synonym für GetProcAddress)
http://audorra.svn.sourceforge.net/v...36&view=markup
Andreas
"Sollen sich auch alle schämen, die gedankenlos sich der Wunder der Wissenschaft und Technik bedienen, und nicht mehr davon geistig erfasst haben als die Kuh von der Botanik der Pflanzen, die sie mit Wohlbehagen frisst." - Albert Einstein
  Mit Zitat antworten Zitat
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#6

Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde

  Alt 12. Mär 2010, 15:43
Zitat von igel457:
"External" sollte auch ohne {$MODE DELPHI} funktionieren.
Tut es aber leider nicht, wenigstens bei mir nicht. Ohne den Delphimodus bricht das Compilieren an der (beispielhafte) Zeile

function OpenThread; external kernel32 name 'OpenThread'; mit der Fehlermeldung

unit1.pas(32,20) Fatal: Syntax error, ":" expected but ";" found ab. Auch alle Bemühungen, den Fehlermeldungen des Compilers entsprechend, diesem die Codezeile schmackhaft zu machen (und sich damit immer mehr vom ursprünglichen Delphi-Quelltext bzw. der Delphi-Syntax zu entfernen), schlugen fehl.

Danke für die Mühe, aber bei Dingen, die ich nur knapp bewältige, die eher mich regieren als umgekehrt, bin ich Dünnbrettbohrer. Bin froh, daß es jetzt überhaupt läuft...
  Mit Zitat antworten Zitat
Benutzerbild von igel457
igel457

Registriert seit: 31. Aug 2005
1.622 Beiträge
 
FreePascal / Lazarus
 
#7

Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde

  Alt 12. Mär 2010, 16:02
Eine Funktion benötigt auch einen Rückgabewert. Und im verlinkten OGG-Header von FPC geht es auch ohne "Mode DELPHI".
Andreas
"Sollen sich auch alle schämen, die gedankenlos sich der Wunder der Wissenschaft und Technik bedienen, und nicht mehr davon geistig erfasst haben als die Kuh von der Botanik der Pflanzen, die sie mit Wohlbehagen frisst." - Albert Einstein
  Mit Zitat antworten Zitat
Benutzerbild von JamesTKirk
JamesTKirk

Registriert seit: 9. Sep 2004
Ort: München
604 Beiträge
 
FreePascal / Lazarus
 
#8

Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde

  Alt 12. Mär 2010, 20:23
So... *Ärmel hochkrempelt*

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
  var
  DLLHandle,hProcessSnap: THandle;
  Beispielfunktion: function(dwFlags:Integer;th32ProcessID:Integer):THandle;//alternativ Funktionsergebnistyp:Pointer, mit dem klappt es aber auch nicht
begin
  DLLHandle := LoadLibrary(kernel32);
  if (DLLHandle < HINSTANCE_ERROR) then showmessage('DLL konnte nicht geladen werden!')
  else
    begin
    Beispielfunktion := @GetProcAddress(DLLHandle, 'CreateToolhelp32Snapshot');//klappt auch nicht, wenn ich das „@“ weglasse
    //hProcessSnap:=CreateToolHelp32SnapShot(2{TH32CS_SNAPPROCESS},0);

    FreeLibrary(kernel32)
    end
end;
Ich erkläre dir mal die Ursache im ObjFPC-Modus:
Das Problem ist hier, dass du der Variable "Beispielfunktion" einen Verweis auf die GetProcAddress-Funktion übergibst, welche sich natürlich unterscheiden. Richtig wäre hier folgendes:

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
type
  // wir benötigen einen Typ, zu dem wir casten können
  TCreateToolhelp32SnapshotProc = function(dwFlags: Integer; th32ProcessID: Integer): THandle; stdcall; // vergiss hier das stdcall nicht!
var
  DLLHandle,hProcessSnap: THandle;
  Beispielfunktion: TCreateToolhelp32SnapshotProc;
begin
  DLLHandle := LoadLibrary(kernel32);
  if (DLLHandle < HINSTANCE_ERROR) then showmessage('DLL konnte nicht geladen werden!')
  else
    begin
    // hier müssen wir jetzt auf den korrekten Typ casten
    Beispielfunktion := TCreateToolhelp32SnapshotProc(GetProcAddress(DLLHandle, 'CreateToolhelp32Snapshot'));
    //hProcessSnap:=CreateToolHelp32SnapShot(2{TH32CS_SNAPPROCESS},0);
    // aufrufen würdest du sie jetzt so:
    hProcessSnap := Beispielfunktion(2, 0);

    FreeLibrary(kernel32)
    end
end;
Ich weiß jetzt allerdings nicht aus dem Stegreif, ob der Code so dann auch unter Delphi funktioniert.

Du hast folgenden Code als Beispiel gepostet:
Delphi-Quellcode:
interface

function OpenThread(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle; stdcall;

implementation

function OpenThread; external kernel32 name 'OpenThread';
Das Problem hier ist, das dies in meinen Augen eine Unsauberkeit des Delphi-Compilers ist. Dies sehen auch die Entwickler von Free Pascal so, weswegen sie dies nur im Delphi-kompatiblen Modus erlauben. Sowohl unter Delphi, als auch unter FPC (egal ob Modus ObjFPC oder Delphi) funktioniert folgender Code:

Delphi-Quellcode:
interface

function OpenThread(dwDesiredAccess: DWORD; bInheritedHandle: BOOl; dwProcessId: DWORD): THandle; stdcall; external kernel32 name 'OpenThread';

implementation
Hier stehen beide Angaben im Interface, was meiner Ansicht nach auch sauberer aussieht.

Und jetzt noch ein Tip am Rande: Unter Free Pascal findet sich die CreateToolHelp32SnapShot Funktion in der Unit jwatlhelp32.pas, die sich im Ordner %FPCDIR%\packages\winunits-jedi\src befindet (wobei %FPCDIR% z. B. "C:\lazarus\fpc\2.2.4" sein kann). Du brauchst den Pfad allerdings nicht mit angeben, da die Units in den Unterverzeichnissen von Packages alle in der Konfiguration von Free Pascal eingetragen sind (insofern sie für die jeweilige Plattform kompiliert wurden).
Allgemein finden sich - meines Wissens - fast alle WinAPI Funktionen in winunits-jedi. Ein Teil davon bzw die übrigen sind dann in packages/winunits-base oder rtl/win zu finden.

Gruß,
Sven
Sven
[Free Pascal Compiler Entwickler]
this post is printed on 100% recycled electrons
  Mit Zitat antworten Zitat
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#9

Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde

  Alt 12. Mär 2010, 21:38
Das war/ist mehr, als das kühnste Horoskop zu träumen bwz. zu prognostizieren wagte, tausend Dank(s), JamesTKirk!

So ungefähr kann ich auch alles nachvollziehen. Das wichtigste ist aber, daß ich auf die Unit „tlhelp32.pas“ bzw. auf die Verrenkungen, einzelne ihrer Funktionen zu extrahieren und woanders einzubinden, verzichten kann, wenn die mit Lazarus mitgelieferte Unit „jwatlhelp32.pas“ eine ähnliche oder sogar die gleiche Funktionalität liefert.

Bevor mir diese Informationen vorlagen, gelang es mir, die Unit „tlhelp32.pas“ mit dem o.g. Delphi-Compilerschalter fehlerfrei zu compilieren. Mit deren Funktionen wäre wohl auch ein Weiterarbeiten möglich gewesen, aber ich benutze natürlich lieber die Lazarus-Lieferpakete.

Zuguterletzt sind die in dieser Diskussion gespeicherten Kenntnisse hoffentlich auch für andere nützlich. Die 1:1-Mal-Eben-So-Portiert-Kompatibilität zwischen Delphi und Lazarus sieht in der Praxis eben doch ganz anders aus: Der Teufel steckt auch hier, wie bekanntlich (fast) überall, im Detail.
  Mit Zitat antworten Zitat
Benutzerbild von JamesTKirk
JamesTKirk

Registriert seit: 9. Sep 2004
Ort: München
604 Beiträge
 
FreePascal / Lazarus
 
#10

Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde

  Alt 12. Mär 2010, 21:51
Schön, dass ich dir weiterhelfen konnte.

Möchtest du eigentlich an dem Programm, in dem du tlhelp32 benötigst, parallel mit Delphi und Lazarus arbeiten oder nur mit Lazarus?

Bei ersterem hätte ich noch zwei verschiedene Vorschläge, mit denen du dir dein Leben erleichtern könntest.

Gruß,
Sven
Sven
[Free Pascal Compiler Entwickler]
this post is printed on 100% recycled electrons
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 6     12 34     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:25 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz