Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Funktion aus DLL einbinden (https://www.delphipraxis.net/190014-funktion-aus-dll-einbinden.html)

RandomDD 22. Aug 2016 00:09

Funktion aus DLL einbinden
 
Ich tu mich gerade ein bisschen schwer dabei, eine einzelne Funktion aus einer DLL in meine DPR-Datei einzubinden.
Ich benötige nur ShellExecute und möchte wirklich ungern die komplette ShellAPI einbinden.

Wie binde ich diese eine einzelne Funktion ein?

Das hier funktioniert nicht :roll:

Delphi-Quellcode:
{$R *.res}

function ShellExecute; external 'shell32.dll' name 'ShellExecuteA';

Luckie 22. Aug 2016 01:51

AW: Funktion aus DLL einbinden
 
Kurze Google oder Forensuche: https://www.delphi-treff.de/tutorial...pascal/dlls/6/

Oder: http://michael-puff.de/Programmierun...ch_laden.shtml

Delphi-Quellcode:
type
  TShellexecute = function(hWnd: HWND; Operation, FileName, Parameters,
    Directory: PChar; ShowCmd: Integer): HINST; stdcall;

procedure TForm1.Button1Click(Sender: TObject);
var
  hLib: cardinal;
  MyShellExecute: TShellexecute;
begin
  hLib := LoadLibrary('shell32.dll');
  if hLib <> 0 then
  begin
    @MyShellexecute := GetProcAddress(hLib, 'ShellExecuteA');
    if not Assigned(MyShellexecute) then
    begin
      RaiseLastOSError;
      exit;
    end;
  end
  else
  begin
    RaiseLastOSError;
    exit;
  end;
  MyShellexecute(Form1.Handle, 'open', 'Notepad.exe', nil, nil, SW_NORMAL);
end;

hoika 22. Aug 2016 04:22

AW: Funktion aus DLL einbinden
 
Hallo,
durch Einbinden einer Unit wird nicht die komplette Unit in die Exe reinkompiliert.
Der Linker schmeißt nicht benutzte Funktionen raus.

Der Code von Luckie ist natürlich trotzdem kleiner ...

Neutral General 22. Aug 2016 07:55

AW: Funktion aus DLL einbinden
 
Alternativ zu dem was Luckie gepostet hat (dynamische Bindung) gibt es noch die etwas weniger aufwendigere statische Bindung:
Delphi-Quellcode:
function Shellexecute(hWnd: HWND; Operation, FileName, Directory: PChar; ShowCmd: Integer): HINST; stdcall; external 'shell32.dll' name 'ShellExecuteA';

procedure TForm1.Button1Click(Sender: TObject);
begin
  Shellexecute(Form1.Handle, 'open', 'Notepad.exe', nil, nil, SW_NORMAL);
end;

jaenicke 22. Aug 2016 08:28

AW: Funktion aus DLL einbinden
 
Beide Quelltexte sind so nicht korrekt, da sie nicht unter allen Delphiversionen funktionieren.
Korrekt wäre:
Delphi-Quellcode:
{$IFDEF UNICODE}
function Shellexecute(hWnd: HWND; Operation, FileName, Directory: PWideChar; ShowCmd: Integer): HINST; stdcall; external 'shell32.dll' name 'ShellExecuteW';
{$ELSE}
function Shellexecute(hWnd: HWND; Operation, FileName, Directory: PAnsiChar; ShowCmd: Integer): HINST; stdcall; external 'shell32.dll' name 'ShellExecuteA';
{$ENDIF}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Shellexecute(Form1.Handle, 'open', 'Notepad.exe', nil, nil, SW_NORMAL);
end;
Denn PChar ist je nach Delphiversion PAnsiChar oder PWideChar. Deshalb ist es falsch den Metatyp PChar bei API-Deklarationen zu benutzen.

Wenn die oben geposteten Quelltexte unter Delphi 2009 oder höher benutzt würden, würde es einen Fehler geben, da nur das erste Zeichen an die Ansi-deklarierte Funktion übergeben würde.

himitsu 22. Aug 2016 11:03

AW: Funktion aus DLL einbinden
 
PChar darf man gern verwenden, wenn die "Funktion" wirklich dynamisch ist.
Delphi-Quellcode:
function Shellexecute(hWnd: HWND; Operation, FileName, Directory: PChar; ShowCmd: Integer): HINST; stdcall;
  external 'shell32.dll' name {$IFDEF UNICODE}'ShellExecuteW'{$ELSE}'ShellExecuteA'{$ENDIF};
Aber grundsätzlich stimmt es schon, bei den meisten WinAPIs -> xxxA mit PAnsiChar, xxxW mit PWideChar und xxx mit PChar (wird in den C++-Headern auch so gemacht und die Delphi-Headerübersetungen selber machen das auch schon länger so)

RandomDD 22. Aug 2016 11:47

AW: Funktion aus DLL einbinden
 
Danke für eure Hilfe. Ich benutze nun folgende Deklaration mit Parameters.

Delphi-Quellcode:
function ShellExecute(hWnd: hWnd; Operation, FileName, Parameters, Directory: PWideChar; ShowCmd: Integer): HINST; stdcall; external 'shell32.dll' name 'ShellExecuteW';

Luckie 22. Aug 2016 12:45

AW: Funktion aus DLL einbinden
 
Zitat:

Zitat von jaenicke (Beitrag 1345381)
Beide Quelltexte sind so nicht korrekt, da sie nicht unter allen Delphiversionen funktionieren.

Der Quellcode ist entstanden, als man bei Delphi noch nicht mal wusste, was Unicode überhaupt ist. Und etwas als falsch zu bezeichnen, weil der Code unter neuen Delphi Versionen so nicht mehr läuft, finde ich etwas dreist.

jaenicke 22. Aug 2016 14:39

AW: Funktion aus DLL einbinden
 
Ich habe damals auch immer den konkreten Typ verwendet (nachdem ich es gelernt hatte), weil das andere nun einmal ein Metatyp war und ist. Das ist ja nicht neu, sondern war damals auch schon so.
Sich darauf zu verlassen, dass der immer auf Ansi zeigt, war da auch schon falsch.

Ob PChar später wirklich Unicode wird, war natürlich nicht klar (war aber zu vermuten aus dem Delphiquelltext heraus), aber klar war, dass PAnsiChar und PWideChar bereits exakt definiert waren und heute ja weiter sind...

Und wenn man mal in den Quelltext von Delphi 4 (!) schaut, da gab es die Unterscheidung ja auch schon...
Delphi-Quellcode:
function GetCommandLineA; external kernel32 name 'GetCommandLineA';
function GetCommandLineW; external kernel32 name 'GetCommandLineW';
function GetCommandLine; external kernel32 name 'GetCommandLineA';
Wenn man das dann damals aus Unwissenheit anders gemacht hat, ist das ja in Ordnung. Aber zu sagen, dass es korrekt war, finde ich nicht richtig. Unwissenheit schützt vor Strafe bzw. hier Problemen nicht.

// EDIT:
Zitat:

Zitat von Luckie (Beitrag 1345396)
Der Quellcode ist entstanden, als man bei Delphi noch nicht mal wusste, was Unicode überhaupt ist.

Das ist schlicht falsch. Da brauchst du nur in die alten Delphiversionen schauen. Nur weil der Stringtyp in Delphi nicht Unicode war, heißt das noch lange nicht, dass es kein Unicode gab. PWideChar konntest du da problemlos verwenden um die Unicodefunktionen aufzurufen.

p80286 22. Aug 2016 15:04

AW: Funktion aus DLL einbinden
 
Seid doch so lieb und kommt wieder runter.
Die meisten von uns haben doch immer noch Char=AnsiChar-Leichen im Keller liegen, und den meisten ist klar, daß das Leichen sind.
Nur falls irgendein Naivling daher kommt und Char in jedem Fall mit Byte übersetzt, sollte man mindestens da wo es notwendig ist mit AnsiChar oder WideChar oder Shortstring oder Ansistring oder .... typisieren.
"korrekt" ist übrigens eine Eigenschaft, die stark von ihrer Umgebung abhängig ist.
Es gibt ja genügend Beispiele für etwas was mal korrekt war und heute dieses Prädikat überhaupt nicht mehr verdient.

Gruß
K-H

EWeiss 22. Aug 2016 15:34

AW: Funktion aus DLL einbinden
 
Wo ist das Problem..
Das eine hat genauso seine Berechtigung wie das andere.

Man muss sich nur darüber im klaren sein was man nun will... A oder W
Kinderkram sich deswegen jetzt aufzuregen.

Wenn ich meine Code in Unicode.. W schreibe dann benötige ich keine {$IFDEF UNICODE} Anweisung genauso umgekehrt.
Ist unnötiger Ballast..
Es wäre nur in dem Fall nötig wenn ich eine Versions Übergreifende Anwendung (Komponente) zur Verfügung stelle die alle auch älter Delphi Versionen Abdecken soll.


gruss

Neutral General 22. Aug 2016 15:40

AW: Funktion aus DLL einbinden
 
Ich glaube ihr redet mindestens zu 50% aneinander vorbei.
jaenicke sagt nur, dass PChar + ShellexecuteA + Delphi 2009 oder höher in die Hose geht.
Und da hat er Recht. Da gibt es nichts dran zu diskutieren.

Ob mans nun mit Compilerschaltern richtig macht oder explizit PAnsiChar + ShellexecuteA bzw. PWideChar + ShellexecuteW benutzt ist letztendlich ja mehr oder weniger egal.

EWeiss 22. Aug 2016 18:00

AW: Funktion aus DLL einbinden
 
Zitat:

jaenicke sagt nur, dass PChar + ShellexecuteA + Delphi 2009 oder höher in die Hose geht.
Und da hat er Recht. Da gibt es nichts dran zu diskutieren.
Und was sagt das nun aus?
Es sollte doch klar sein das man ShellexecuteA mit PChar (WideChar) nicht verwenden kann.
Dafür benötige ich aber keine Compilerschalter um das richtig zu stellen.

Zitat:

Ob mans nun mit Compilerschaltern richtig macht oder explizit PAnsiChar + ShellexecuteA bzw. PWideChar + ShellexecuteW benutzt ist letztendlich ja mehr oder weniger egal.
Nö ist nicht egal.

Entweder ich schreibe meine Anwendung in Unicode oder halt nicht. (Das geht ohne den zusätzlichen Ballast)
Das jeder glaubt irgendwelche Schalter umlegen zu müssen damit etwas funktioniert.
Es gibt letztendlich nur eins, 0 oder 1.

Mal abgesehen davon das der Compiler wenn er denn richtig tickt es eh nicht zulassen würde.

gruss

jaenicke 22. Aug 2016 18:31

AW: Funktion aus DLL einbinden
 
Zitat:

Zitat von EWeiss (Beitrag 1345424)
Und was sagt das nun aus?
Es sollte doch klar sein das man ShellexecuteA mit PChar (WideChar) nicht verwenden kann.

Die Quelltexte oben hast du aber schon gesehen, oder? Da ist es ja eben gerade nicht so...
Sonst hätte ich auch nichts geschrieben...

//edit:
Und ohne Ballast geht auch indem man PWideChar plus W-Variante benutzt. Das funktioniert dann sogar im zugegebenermaßen unwahrscheinlichen Fall, dass PChar irgendwann auf UTF-8 zeigt...

Luckie 22. Aug 2016 18:43

AW: Funktion aus DLL einbinden
 
Nur zu dem Zeitpunkt, als der Code entstanden ist, hat ihn niemand angemäkelt.

jaenicke 22. Aug 2016 20:05

AW: Funktion aus DLL einbinden
 
2005 oder 2006 habe ich zu ähnlichen Beiträgen genau das geschrieben. Leider finde ich das aktuell nicht mehr.
Spielt aber auch keine Rolle. Ich habe ja nur geschrieben, dass am RTL Quelltext damals zu sehen war wie es gemacht werden sollte.


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:56 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz