![]() |
DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinden?
Hallo allerseits!
Seit geraumer Zeit suche ich mir einen Wolf im www, leider vergeblich. Kurzum: Ist es möglich, in Lazarus / Freepascal DLL-Funktionen einzubinden, und, falls ja, wie? Besten Dank im voraus! Gruß Delphi-Laie |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Mit Sicherheit. Unter Windows mit den üblichen Windows-API Funktionen:
![]() ![]() ![]() |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Es gibt allerdings, wie ich gerade herausfand, in Lazarus eine Unit "Windows" (einfach probehalber manuell mit eingebunden, wird erkannt bzw. akzeptiert). Damit scheint mein Ansinnen schon deutlich günstiger auszusehen. :-D |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Wäre ja irgendwie etwas selten dämlich, wenn man mit FreePascal Windows Programme erstellen könnte, es aber keine Möglichkeit gäbe Windows Funktionen zu nutzen.
|
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Edit: Mein anfänglicher Optimismus ist leider schon wieder stark gedämpft: Lazarus kennt auch mit eingebundener Unit "windows" den Befehl "GetProcAddress" nicht. Dieser ist m.E. aber nötig, um DLL-Funktionen in den DLLs zu lokalisieren. |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
![]() |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Um dir noch etwas mehr auf die Sprünge zu helfen:
(Un)LoadLibrary und GetProcAddress sind plattformunabhängig in der Unit DynLibs definiert. Mit SharedSuffix hast du übrigens dann auch noch eine Konstante für die Dateierweiterung ('.dll' unter Windows und '.so' unter Linux). Die Unit Windows kannst du wieder aus deiner Uses entfernen, außer du möchtest explizit nur für Windows programmieren. Zitat:
Gruß, Sven |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Besten Dank, also man muß mindestens die Units windows und dynlibs einbinden, um DLL-Funktionen aufrufen bzw. benutzen zu können.
Zitat:
![]()
Delphi-Quellcode:
Dank der beiden nunmehr bekannten und eingebundenen Units bekomme ich ein analoges Beispiel auch endlich (fehlerfrei) compiliert. So, jetzt hat man ein PHandle auf die gewünschte Funktion. Wie man damit jetzt seine Wunschfunktion aufrufen kann, ist mir allerdings leider immer noch unklar. Ich bitte um Nachsicht, daß ich mal wieder ein Anfänger bin. Ich versuche, mit dieser Funktion "GetProcAdress" eine Lösung dafür im Internet zu finden.
procedure TForm1.KOLForm1FormCreate(Sender: PObj);
var DLLHandle: THandle; u:Integer; returnhandle: PHandle; begin DLLHandle := Windows.LoadLibrary(SimpleLibName); if (DLLHandle < HINSTANCE_ERROR) then begin Label1.Caption:='DLL konnte nicht geladen werden!'; end; returnhandle := GetProcAddress(DLLHandle, 'HTCSensorOpen'); end; Zitat:
|
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Einfach nur Pointer. Oder besser noch ein Zeiger auf eine Funktion, bzw. (zumindestens in Delphi) ein Funktions-Typ. (Delphi weiß ja intern, das man damit einen Zeiger meint) viele Beispiele siehe ![]()
Delphi-Quellcode:
var func: function(params): result;
//type tfunc = function(params): result; //var func: tfunc; func := GetProcAddress... |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Vielen, herzlichen Dank für Eure Mühen, aber nach Stunden erfolgslosen Probierens stehe ich nunmehr total auf dem Schlauch, wie ich es Delphi schon seit Jahren nicht mehr erlebte.
Anscheinend geht es in etwa darum, die Delphi-Kapselung vieler API-Funktionen in Lazarus nachzubilden. Ich versuche beispielhaft, die CreateToolhelp32Snapshot-Funktion zunächst erst einmal erfolreich aufzurufen, scheitere daran aber natürlich (konkret schon in der Zeile davor, in der ich die Beispielfunktion wertzuweisen beabsichtige):
Delphi-Quellcode:
An die Kryptigkeit der Fehlermeldungen habe ich mich auch längst gewöhnt, aber vor
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;
Delphi-Quellcode:
kapituliere ich. Um nur mal die zweite Fehlermeldung zu kommentieren: Warum darf ich GetProcAddress auf einmal nicht mehr mit Parametern aufrufen?
unit1.pas(38,25) Error: Incompatible types: got "<address of function(LongInt, AnsiString):^untyped;Register>" expected "<procedure variable type of function(LongInt, LongInt):DWord;Register>"
unit1.pas(38,40) Fatal: Syntax error, ";" expected but "(" found 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'; |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
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; |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Danke auch für Deine Mühe!
Zitat:
Zitat:
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:
|
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Die ganze Kunst scheint darin zu bestehen, den Kommandozeilenschalter
Delphi-Quellcode:
zu verwenden, damit scheint es erstmal zu klappen.
{$mode DELPHI}
Tausend Dank für die Geduld an alle! Problem (erstmal?) geklärt.... |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
"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): ![]() Acinerella Header (von mir, statisches Laden): ![]() Libao Header (von mir, dynamisches Laden, AcGetProcAddress ist (fast) nur ein Synonym für GetProcAddress) ![]() |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Delphi-Quellcode:
mit der Fehlermeldung
function OpenThread; external kernel32 name 'OpenThread';
Delphi-Quellcode:
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.
unit1.pas(32,20) Fatal: Syntax error, ":" expected but ";" found
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... |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Eine Funktion benötigt auch einen Rückgabewert. Und im verlinkten OGG-Header von FPC geht es auch ohne "Mode DELPHI".
|
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
So... *Ärmel hochkrempelt*
Delphi-Quellcode:
Ich erkläre dir mal die Ursache im ObjFPC-Modus:
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; 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:
Ich weiß jetzt allerdings nicht aus dem Stegreif, ob der Code so dann auch unter Delphi funktioniert.
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; Du hast folgenden Code als Beispiel gepostet:
Delphi-Quellcode:
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:
interface
function OpenThread(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle; stdcall; implementation function OpenThread; external kernel32 name 'OpenThread';
Delphi-Quellcode:
Hier stehen beide Angaben im Interface, was meiner Ansicht nach auch sauberer aussieht.
interface
function OpenThread(dwDesiredAccess: DWORD; bInheritedHandle: BOOl; dwProcessId: DWORD): THandle; stdcall; external kernel32 name 'OpenThread'; implementation 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 |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
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. |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Schön, dass ich dir weiterhelfen konnte. :mrgreen:
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 |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Aber mit Vorschlägen mußt Du trotzdem keinesfalls geizen, die können - wem auch immer - in Situationen helfen, die man vorher gar nicht ahnt. |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Mal schauen, dass ich das mal an die FPC Entwickler melde... Zitat:
Binde die (jwa)tlhelp32 Units folgendermaßen ein:
Delphi-Quellcode:
Die andere Möglichkeit ist es die Units im Verzeichnis %FPCDIR%\packages\winunits-jedi\src in den Unit-Suchpfad von Delphi einzutragen und einfach die jwatlhelp32 Unit sowohl in Delphi, als auch in Free Pascal zu verwenden. Eventuell solltest du dann allerdings noch deinen DCU-Ausgabepfad anpassen oder du kopierst den jedi Ordner woanders hin, damit der Ordner nicht mit DCUs vollgestopft wird. So weit ich das sehe sollten die jwa* Units alle Delphi kompatibel sein.
uses
// andere Units {$ifdef fpc} jwatlhelp32, {$else} tlhelp32, {$endif} // andere Units Dadurch kannst du den Code (im Idealfall) sowohl unter Delphi, als auch unter Free Pascal verwenden. EDIT: ok... hab nochmal genauer nachgeschaut. In den Includes von Free Pascal ist das DYNAMIC_LINK Define deaktiviert, das dafür sorgt, dass diese Assembleroutinen verwendet werden... also ist alles im grünen Bereich (das statische Linken mit "external" wird verwendet) und 64-Bit sollte kein Problem darstellen :mrgreen: EDIT2: doppeltes Wort entfernt -.- Gruß, Sven |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Herzlichen Dank!
Mit bedingten Compilierungen bzw. Compilerschaltern dafür innerhalb des uses-Befehles hatte ich schon mit Delphi bisher nur schlechte Erfahrungen. Schon bei einem anderen Programm probierte ich nämlich erfolglos, abhängig von der Delphiversion, bestimmte units nur optional einbinden. Auch mit Lazarus will es nicht funktionieren. Alternativ jeweils den kompletten uses-Befehl in die Compilerschalter einzubinden (müßte doch eigentlich auch möglich sein?!), funktioniert in meiner DLL-Quelltextprojektdatei auch nicht - beißt sich das evtl. mit dem Delphi-Modus, den ich vorher deklarieren muß, damit es keinen Fehler gibt? Mein unter WindowsXP(64) laufendes Lazarus compilierte die im selben Verzeichnis befindliche tlhelp32.pas (diese natürlich im Delphi-Modus) erst, nachdem ich die Schalter und auch jwathelp32 aus dem uses-Befehl meiner DLL-Quelltextdatei entfernte (auskommentierte). Es handelt sich ohnehin um ein reines Windowsprogramm, warum also solche Verrenkungen, die wohl eine gewisse Plattformunabhängigkeit erreichen sollen? Ich glaube kaum, daß andere Betriebsprogramme die gleichen Hooks verwenden, ja, ich weiß nicht einmal, ob die überhaupt welche oder ersatzweise ähnliche Funktionalitäten zur Verfügung stellen. Unter 32- und unter 64-Bit-Windows-Lazarus konnte ich immerhin die DLL-Quelltexte erfolgreich compilieren und bin damit schon weiter, als ich es zu hoffen wagte. Das 32-Bit-Compilat funktioniert in Zusammenarbeit mit dem in Delphi geschriebenen 32-Bit-Hostprogramm sogar schon (jippie!), und das immerhin zur Zufriedenheit: Die Hooks werden eingeschaltet und lösen die gewünschten Aktionen aus; es kommt von der Funktionalität her knapp an das Delphi-Compilat heran. Zwei kleine Dinge funktionieren nicht, aber die sind beide nicht(s) weltbewegend(es). Nunmehr stehe ich vor der Aufgabe, das Hostprogramm 64 Bit mit Lazarus zu schreiben, denn das 32-Bit-Delphi-Compilat des Hostprogrammes verweigert, wie zu erwarten, die Zusammenarbeit mit der 64-Bit-DLL (es findet die DLL nicht einmal, obwohl im selben Verzeichnis liegend). Mit einem einfach Umbenennen der dpr- in eine lpr-Datei ist es natürlich beileibe nicht getan. Entweder funktioniert das dann mit einer DLL, in die units tlhelp32- und/oder einer tlhelp32 eingebunden werden, oder eben nicht. Ich lasse mich überraschen. Dir nochmals unzählige Danks! |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Zitat:
Zitat:
Zitat:
Gruß, Sven |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Delphi-Quellcode:
noch
{$mode DELPHI}{$H+}
uses Windows, Classes, {$ifdef fpc} jwatlhelp32, {$else} tlhelp32, {$endif} SysUtils;
Delphi-Quellcode:
compilieren die tlhelp32-unit, erst, wenn ich die explizit aufrufe und damit das Compilieren erzwinge. Übrigens, {$mode DELPHI}{$H+} scheint auch ohne {$H+} zu funktioneren, also nur {$mode DELPHI} bzw. {$mode DELPHI}//{$H+}
{$mode DELPHI}{$H+}
{$ifdef fpc} uses Windows, Classes, jwatlhelp32, SysUtils; {$else} uses Windows, Classes, tlhelp32, SysUtils; {$endif} Zitat:
Zitat:
Zitat:
|
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Delphi-Quellcode:
{$mode DELPHI}{$H+}
uses Windows, Classes, {$ifdef fpc} jwatlhelp32, {$else} tlhelp32, {$endif} SysUtils;
Delphi-Quellcode:
Hmm... beide Varianten müssten zumindest mit Free Pascal funktionieren... Unter Delphi sollten sie auch komplieren, wenn du den Mode-Schalter folgendermaßen ergänzt:
{$mode DELPHI}{$H+}
{$ifdef fpc} uses Windows, Classes, jwatlhelp32, SysUtils; {$else} uses Windows, Classes, tlhelp32, SysUtils; {$endif}
Delphi-Quellcode:
Das liegt daran, dass Delphi den Modeswitch nicht kennt und im Gegensatz zu Free Pascal unbekannte Switches nicht ignoriert... Nach allem was ich weiß und verwende, sollte es dann funktionieren... Wenn nicht bleibt mir nur noch ein erstauntes "WTH?! :shock: ".
{$ifdef fpc}
{$mode delphi}{$H+} {$endif} Zitat:
Zitat:
Zitat:
Gruß, Sven |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Zitat:
Eine Kompatibilität bezüglich Lazarus und Delphi reizt mich durchaus auch, aber ich verbeiße mich nicht darin. Auf ein animiertes TrayIcon (sehr komfortabel und ergonomisch, eben lässig) werde ich aber verzichten müssen, weil das die TTrayIcon-Komponente in Lazarus nicht kennt - vielleicht wird die ja noch nachgerüstet. Ich kenne das noch von CoolTrayIcon, und erstaunlicherweise hat auch die Delphi-TTrayIcon-Komponente (oder meinetwegen auch -Klasse) diese Königsdisziplin-Funktion(alität) aufzuweisen. Wenn ich nicht weiterkomme oder fertigbin, melde ich mich wieder, dann im ersten Fall hier, im anderen Falle im Thread, wo ich schon die 32-Bit-Variante vorstellte; Dich werde ich dann persönlich informieren. Nochmals allerbesten Dank! |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Zitat:
Code:
Free Pascal ist da freizügiger, weil man ja nicht weiß, auf was für Ideen (bzgl. Compilerswitches) die Jungs von Borland/CodeGear/Embarcadero noch so kommen... :?
Fehler: Ungültige Compileranweisung: 'mode'
Zitat:
Gruß, Sven |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Danke!
Jetzt - auf einmal - ist mir der Schalter für den FP-Compiler klar. Ich muß auch ein wenig um Nachsicht bitten, denn ich irrte mich. Compilerschalter in der uses-Anweisung in Delphi benutzte ich doch schon erfolgreich, wie meine Recherche ergab. Was die TrayIcons unter Lazarus anbetrifft, schaue bitte bei Interesse ![]() Ganz klar ist mir das dort zwar noch nicht, aber ich kämpfe mich voran. Warum ausgerechnet die mit Delphi gleichnamige Klasse mit Delphi inkompatibel sein soll, verschließt sich mir. Auch gelang es mir nicht, ein Objekt der (angeblich) delphikompatiblen Klasse Systrayicon zu erzeugen, weil ich nicht mal die genaue Typbezeichnung kenne (SysTrayIcon, was dort steht, funktioniert jedenfalls nicht, auch nicht als TSysTrayIcon). Benötigt man dafür mal wieder eine spezielle Unit, die dort nicht steht, analog jwatlhelp32, die mir auch unbekannt war? Und welchen Sinn soll eine nichtvisuelle TrayIcon-Klasse haben?! Egal, das sind nur rhetorische Fragen, mit TTrayIcon mache ich gerade herum, das funktioniert wenigstens. Die Delphikompatibilität behalte ich weiterhin im Auge, aber sie ist (für mich) nicht zwingend. |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Grüezi!
Also Du hattest recht: Die Lazarus-Unit „jwatlhelp32“ scheint in der 64-Bit-Version des Lazarus' (gibts auch eine 64-Bit-Version dieser Unit?) die Toolhelpfunktionen nicht zu unterstützen. :( So schnell gebe ich naütürlich nicht auf. Lazarus die Unit „tlhelp32.pas“, also in Quelltextversion (die simpelste von Delphi 2.0, da sind alle für mich relevanten, entscheidenden Funktionen schon enthalten) untergeschoben, wird auch fehlerfrei compiliert und eingebunden, also die Exe wird erstellt. Wiederum sind jedoch keine Toolhelpfunktionen verfügbar. Sooo schnell gebe ich allerdings nicht auf. Auf Dateinamensgleichheit geprüft (müßte aber stimmen, sonst gäbe es ja eine Fehlermeldung), und tatsächlich, auch unter meinem Windows XP 64 Bit heißt die angesprochene, angeforderte DLL „kernel32.dll“. Zur Sicherheit auch noch den Dependency Walker darübergejagt, doch auch die Funktionen in(nerhalb) der DLL schmücken sich inkonsequenterweise mit dem Zusatz (der Endung) „32“. Nun tauschte ich alle DWORD-Typdeklarationen in der „tlhelp32.pas“ mit „Int64“ aus. Auch das wird fehlerfrei compiliert und eingebunden. Doch die Toolhelpfunktionen scheinen immer noch nicht zu klappen, zu funktionieren, verfügbar zu sein, was auch immer. Es gibt keine Fehlermeldung, jedoch auch keine Funktionswirkung. Nunmehr bin ich mit meinem Latein, äh, Lazarus allmählich am Ende. :? Weißt Du oder weiß jemand anderes noch einen Rat, Toolhelpfunktionen unter Lazarus 64 Bit verfügbar zu machen? Immer und immer wieder dieser Scheibenkleister (Übergangsprobleme), wenn in der Computerbranche Standards wechseln. Gruß Delphi-Laie |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Zitat:
2. Wie schon geschrieben wurde, sind sehr viele Assemblerblöcke drin, die eben alle für 32 bit geschrieben sind. Die müsste man alle nochmal umschreiben, damit alles vernünftig liefe. Zitat:
Das macht zwar die Portierung auf andere Plattformen unmöglich, aber das scheint ja so wie so keine Rolle zu spielen. [edit]LongWord oben entfernt. Ist mir so dazwischengerutscht. Danke an JamesTKirk für den Hinweis ;D[/edit] |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Gruß, Sven |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
|
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Gruß, Sven |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Tausend Dank für Euer Engagement!
Nun, die Sache ließ mir keine Ruhe. Hier das vorläufige Ergebnis: Ich benutze die beiden Funktionen (die erste stammt weitgehend von Luckie(s Programm „WinInfo“)) zur Ermittlung des Exe-Dateinamens eines Vordergrundfensters:
Delphi-Quellcode:
und (Luckies obige Funktion diente auch hier als Vorlage)
function GetExeStringFromProcID_Processsnapshot(PID:DWORD):string;
var hProcSnap:THandle; pe32:TProcessEntry32; begin hProcSnap:=CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0); if hProcSnap<>INVALID_HANDLE_VALUE then begin pe32.dwSize:=SizeOf(TProcessEntry32); if Process32First(hProcSnap,pe32) then begin if pe32.th32ProcessID=PID then begin result:=ExtractFileName(pe32.szExeFile);//ohne Extraktion wird unter ME (jedes 9.x?) der gesamte Pfad zurückgeliefert CloseHandle(hProcSnap); exit end; while Process32Next(hProcSnap,pe32)do if pe32.th32ProcessID=PID then begin result:=ExtractFileName(pe32.szExeFile); break end end; CloseHandle(hProcSnap) end; end;
Delphi-Quellcode:
Benutze ich die unit „jwatlhelp32“, scheinen sie überhaupt nicht zu funktionieren. In erster Funktion sind alle „32.th32ProcessID“ gleich 0, was natürlich falsch ist (nur der Systemprozeß hat die Nr. 0). Die „me.szExePath“ liefern verstümelte Resultate, z.B. „er.exe“ beim „explorer.exe“ oder „rus.exe“ bei „lazarus.exe“.
function GetExeStringFromProcID_Modulsnapshot(PID:DWORD):string; //stdcall;
var hModuleSnap:THandle; me:TModuleEntry32; begin hModuleSnap:=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,PID); if hModuleSnap<>INVALID_HANDLE_VALUE then begin me.dwSize:=SizeOf(TModuleEntry32); if Module32First(hModuleSnap,me) then begin if uppercase(ExtractFileExt(me.szExePath))='.EXE' then begin result:=ExtractFileName(me.szExePath); CloseHandle(hModuleSnap); exit end; while Module32Next(hModuleSnap,me) do if lowercase(ExtractFileExt(me.szExePath))='.exe' then begin result:=ExtractFileName(me.szExePath); break end end; CloseHandle(hModuleSnap) end end; Unter Windows 32 Bit, mit Lazarus 32 Bit compiliert, funktioniert aber alles tadellos! Die Funktion „CreateToolHelp32SnapShot“ funktioniert allerdings auch in der 32-Bit-Version unter Windows 64 Bit, wie ich anhand meines Programmes „Prozesse“ (auch hier im Forum abgelegt) feststellen konnte. Setze ich Lazarus (64 Bit) die unit „tlhelp32“ von Delphi 2.0 vor, scheint jetzt wenigstens der Modulschnappschuß zu funktionieren (weiß nicht, ob ich vorhin die gleiche Unit oder doch „jwatlhelp32“ benutzte, der Prozeßschnappschuß immer noch nicht. Jedenfalls sind die Ergebnisse völlig inkonsistent, so daß ich allmählich einen Fehler im Free-Pascal-Compiler vermute. Alles Rumgemache, die Variablentypen „DWORD“ und auch „THandle“ mit „Int64“ auszutauschen, auch, einen „Int64“, auch als Konstante schon an die Funktionen zu übergeben, brachten leider auch keinen Erfolg. Zum Glück funktioneren die Hooks unter Windows 64 Bit. Diese Hooks sind allerdings der Grund, daß ich kein 32-Bit-Compilat unter Windows 64 Bit benutzen kann. |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
|
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Setze ich Lazarus (64 Bit) die unit „tlhelp32“ von Delphi 2.0 vor, scheint jetzt wenigstens der Modulschnappschuß zu funktionieren (weiß nicht, ob ich vorhin die gleiche Unit oder doch „jwatlhelp32“ benutzte), der Prozeßschnappschuß immer noch nicht. Jedenfalls sind die Ergebnisse völlig inkonsistent, so daß ich allmählich einen Fehler im Free-Pascal-Compiler vermute. und korrigierte es weiter oben schon. Ja, „eigentlich“ werden die externen Funktionen aus der DLL ja nur aufgerufen, also ist der Compiler nicht so recht als Schuldiger einzugrenzen. Selbst, wenn die DLL nur 32 Bit ist (die vielen „32“, im DLL-Namen und ihre immanenten Funktionen suggerieren das ja), dann müßten sie doch erst recht funktionieren. Ich denke mir das alles nicht aus. Inskonsitente Ergebnisse sind schwer zu beschreiben, deshalb auch eine gewisse Langatmigkeit. |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Ich sollte echt mal ein 64-Bit Windows installieren... ich melde mich dann im Laufe der Woche wieder, sobald ich das geschafft hab und du dein Problem nicht eh schon gelöst hast. :zwinker:
So wird das nämlich nichts. :mrgreen: Gruß, Sven |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Zitat:
Die Lazarus-64-Bit-Version, die ich habe, scheint nicht einmal einen integrierten Debugger zu besitzen (32-Bit-Lazarus hat einen), damit ist es natürlich gänzlich aussichtslos. Ich behalf mich mit Piepton- und Messageboxausgaben, und davon wurde ich immerhin so schlau, daß es ein Process32First gar nicht gibt (heute nachmittag gab es sogar mehrere Process32Next, doch es ergab sich als Process-ID immer nur die Null). Ich band sogar nur die relevanten Codeteile der tlhelp32-Unit in meine beiden Programmdateien (DLL und Hostprogramm) ein, doch ein Erfolgsfortschritt will sich auch damit nicht einstellen. Welch ein Glück, der Modulschnappschuß scheint zu funktionieren. So richtig funktioniert auch nur der eine der beiden Hooks (der Shellhook), allerdings der, den ich ohnehin bevorzuge. Auch viele andere Abstriche mußte ich machen, aber mein Programm läuft nunmehr „gerade so“, daß es noch erträglich ist, aber in der gewünschten Grundfunktionalität: Ich öffne irgendein (Explorer- oder anderes Programm-)Fenster mit skalierbaren Dateianzeigelisten und - flupp, wie von Zauberhand - haben die Spalten automatisch die richtige Breite; etwas, was die Büroklammerntanzprogrammierer bis heute nicht hinbekamen (korrekterweise wohl eher: nicht programmieren durften, denn ich bediene mich auch nur der mitgelieferten Bordmittel). Ich werde an dem 64-Bit-Programm deshalb auch keine Zeit mehr ver(sch)wenden, es sei denn, ich bekomme noch irgendwelche interessanten Anregungen oder eine neue Lazarus-64-Bit-Version. Es kann aber durchaus sein, daß ich mein Programm „Prozesse“ nach Lazarus und dann natürlich auch zu 64 Bit migrieren werde - auch wenn das beileibe nicht so einfach ist, wie von jemandem in diesem Forum behauptet - den Beweis, daß mein o.a. Vermutung richtig ist, hätte ich nämlich selbst gern. Spannend und zukunftsträchtig („zukunftssicher“) sind 64 Bit allemal, nicht nur die aus Redmond! :wink: |
Fehler in Lazarus 64 Bit für Windows?!
Liste der Anhänge anzeigen (Anzahl: 1)
Mein gestriger Verdacht hat sich erhärtet, ja eigentlich schon bestätigt.
Um das festzustellen, bediente ich mich auf die Schnelle Luckies Programmes „WinInfo“, daß ich mal eben so nach Lazarus portierte (wenn alle Portierungen so reibungslos wären!). Lediglich die beiden Vergleiche „= true“ in der Funktion „GetExeStringFromProcID“ entfernte ich, und dieses Entfernen hat seine Richtigkeit, wie er mir schon vor Jahren bestätigte (ich zettelte dazu sogar mal eine Diskussion an, die sehr lebhaft wurde). Kurzum, erwartungsgemäß bleibt das Feld „Anwendung“, das sich dieser o.g. Funktion bedient (die wiederum kernel32-Funktionen benutzt) und den Exe-Dateinamen ausspucken soll, in der 64-Bit-Version leer. Das 32-Bit-Compilat funktioniert jedoch unter beiden Umgebungen. Merkwürdigerweise bekam ich die das Programm mit eingebundener Unit „jwatlhelp32“ weder unter Lazarus 32 noch 64 Bit compiliert - die IDEs fanden sie wohl nicht. Nur mit tlhelp32 ließ es sich kompilieren. Ich lege zum schnellen Ausprobieren (wen es interessiert) den Quelltext (der ja ursprünglich von Luckie stammt, das sei hier noch einmal wiederholt) und die beiden Compilate als Komprimat hier ab. Also, trotz Einbindung externer DLL-Funktionen, für die der Compiler auf den ersten Blick ja nicht verantwortlich ist, stimmt irgendetwas mit dem 64-Bit-Lazarus nicht. Viele Grüße Delphi-Laie Unit jwatlhelp32 wird doch gefunden, war ein Schreibfehler (verdammt schmales kleines L!) meinerseite im Quelltext. Funktioniert aber, wie schon hier in dieser Diskussion vermutet, auch nicht. |
Re: DLL-Funktionen in Lazarus/FP einbindbar / wie einzubinde
Das ist keine Macke, sondern das liegt einfach daran, dass tlhelp32 für 32 Bit geschrieben ist.
Wenn du eine 64-Bit-Version davon gefunden hast, und es immer noch nicht läuft, dann solltest du dich wundern. Aber 32 und 64 Bit sind nunmal unterschiedlich. Da kannste nix machen. Bist du dir sicher, dass die Daten nicht heil bei der DLL ankommen? Vielleicht liegt auch in der der Fehler. Oder ist es gar eine 32-Bit-DLL? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:12 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