![]() |
C++ -> Delphi
Moin,
ich weiss nicht wie es mit Themen ist bei denen es eigentlich ums gleiche geht, neuen Thread oder den alten benutzen egal ob essich um was anderes handelt? Ich möchte einen C++ Code in Delphi-Code umwandeln. Original Code:
Code:
void __stdcall (*LoadDll)(LOADINFO*);
typedef struct { DWORD mVersion; HWND mHwnd; BOOL mKeep; } LOADINFO; Ich habe es so versucht:
Delphi-Quellcode:
Leider gibts beim Aufruf eine AV, jemand ne Ahnung wie es richtig aussehen müsste? <g>
type
PLOADINFO = ^TLOADINFO; TLOADINFO = record mVersion: DWORD; mHwnd: HWND; mKeep: BOOL; end; TLoadDll = procedure(LoadInfo: PLOADINFO); stdcall; var LoadDll: TLoadDll; |
Re: C++ -> Delphi
Na der Variablen muss erst noch ein Wert zugewiesen werden.
Die source ist ein uebliches Konstrukt wenn man mit LoadLobrary() und GetProcAddress() eine DLL dynamisch laedt. |
Re: C++ -> Delphi
Moin Robert,
Wie meinst du das mit Wert zuweisen? <g> Welchen Wert? Wird im obigem C++-Code doch auch nicht gemacht oder? |
Re: C++ -> Delphi
Zitat:
Zeig mal den Code der die Struktur verwendet (C und Delphi). |
Re: C++ -> Delphi
Moin Nico,
der Code steckt in einer DLL die von einem anderen Programm aus (mIRC) aufgerufen wird. Ich quote dir mal den Teil der in der mIRC Hilfe steht: Zitat:
Übrigens habe ich den Methodenzeiger exportiert:
Delphi-Quellcode:
exports
LoadDll; |
Re: C++ -> Delphi
Zitat:
Zitat:
|
Re: C++ -> Delphi
Nunja, Nico, von ausserhalb wird ja die Prozedur "LoadDll", bzw ein Pointer auf diese aufgerufen, wie hätte ich das sonst lösen sollen? LoadDll ist ja der Zeiger auf die Prozedur, oder? :oops:
|
Re: C++ -> Delphi
void __stdcall (*LoadDll)(LOADINFO*);
ist die Deklaration einer Zeigervariablen genau wie var LoadDll: TLoadDll; Globale Variablen werden aber mit NULL/nil initialisiert. Irgendwo im Code muss also der Funktionsvariablen ein Wert zugewiesen werden, damit man die Funktion aufrufen kann. Dasmacht man mit LoadLibrary() und GetProcAddress() um die adresse der Funktion aus der DLL zu bekommen. |
Re: C++ -> Delphi
Zitat:
Delphi-Quellcode:
library Foo;
uses Windows; type PLoadInfo = ^TLoadInfo; TLoadInfo = record mVersion: DWORD; mHwnd : HWND; mKeep : BOOL; end; procedure LoadDll(var LoadInfo: TLoadInfo); stdcall; begin LoadInfo.mKeep = True; end; exports LoadDll; begin end. |
Re: C++ -> Delphi
@Robert: LoadLibrary() verwende ich in der DLL selbst? ich kenn das nur das man das von seinem Programm aus macht um die DLL zu laden. Den Part müsste doch eigentlich mIRC übernehmen.
@Nico: Ich versuche es dann mal umzuändern *g*. Edit: @Nico: Wenn ich "var" bei der Prozedur weglasse, stürzt mirc nicht ab, aber gibt "0" zurück und ein erneuter aufruf führt zum Absturz, wenn ich "var" benutze stürzt mirc direkt beim aufruf ab. (Danke für dein Codebeispiel btw) |
Re: C++ -> Delphi
Ach so, das Zeugs steht in der DLL.
Dann exportiert die DLL eine globale Variable. Ist denn LoadDll unter den exportierten Namen der DLL zu sehen? Wenn nicht, dann ist es eine interne Variable der DLL, aber Variablen muessen auf jeden Fall irgendwo zugewiesen werden. |
Re: C++ -> Delphi
Moin Robert,
Jo, die DLL exportiert sie:
Delphi-Quellcode:
allerdings, da es sich wohl doch nicht um einen Pointer aufd eine Funktion handelt(?) ist das exportierte bereits die Funktion und daher keine(?) Variable.
exports
LoadDll; |
Re: C++ -> Delphi
Zitat:
Delphi-Quellcode:
Exportierte Funktion:
library Foo;
uses Windows; type PLoadInfo = ^TLoadInfo; TLoadInfo = record mVersion: DWORD; mHwnd : HWND; mKeep : BOOL; end; procedure _LoadDll(var LoadInfo: TLoadInfo); stdcall; begin LoadInfo.mKeep = True; end; type TFNLoadDll = procedure(var LoadInfo: TLoadInfo); stdcall; var LoadDll: TFNLoadDll = TFNLoadDll(_LoadDll); exports LoadDll; begin LoadDll := _LoadDll; end.
Delphi-Quellcode:
Ich gehe davon aus, dass mIRC letzteres erwartet.
library Foo;
uses Windows; type PLoadInfo = ^TLoadInfo; TLoadInfo = record mVersion: DWORD; mHwnd : HWND; mKeep : BOOL; end; procedure LoadDll(var LoadInfo: TLoadInfo); stdcall; begin LoadInfo.mKeep = True; end; exports LoadDll; begin end. |
Re: C++ -> Delphi
Moin Nico,
letzteres habe ich direkt übernommen, das hat nicht geklappt (crash). Ich habe gerade mal das erste versucht, dort gab es leider einen Compilerfehler bei:
Delphi-Quellcode:
Er meint das wäre eine ungültige Typumwandlung.
LoadDll: TFNLoadDll = TFNLoadDll(_LoadDll);
|
Re: C++ -> Delphi
Delphi-Quellcode:
würde gehen.
TFNLoadDll(@_LoadDll)
Geht wohl nicht *g* Schlecht wenn man kein Delphi hat... |
Re: C++ -> Delphi
Moin Nico,
hier übrigens was bei letzterer Methode passiert: Aufruf der DLL: ![]() Wenn ich "OK" geklickt habe: ![]() Wenn ich die DLL erneut aufrufe: ![]() Das ShowMessage kommt daher, da ich das testweise mit in der DLL habe:
Delphi-Quellcode:
Übrigens wenn ich es so mache:
procedure LoadDll(var LoadInfo: TLOADINFO); stdcall;
begin LoadInfo.mKeep := True; ShowMessage(IntToStr(LoadInfo.mVersion)); end;
Delphi-Quellcode:
Gibt es einen erneuten Fehler:
LoadDll: TFNLoadDll = TFNLoadDll(@_LoadDll);
Zitat:
|
Re: C++ -> Delphi
Wenn es crasht, dann kommentiere den Code in LoadDll aus.
(statt ShowMessage solltest Du MessageBox verwenden... und entferne alle unnötigen Units (ShareMem, Dialogs, Forms...)) Wie auch immer, soweit ich das in den Tutorials zu mIRC-DLLs sehen kann, ist die zweite Variante korrekt (exportierte Funktion). Falls es bei leerer LoadDll immer noch zu einer Zugriffsverletzung kommt, könnte ich nicht sagen wieso :) |
Re: C++ -> Delphi
Moin Nico,
danke nochmal :) ich hab mal folgendes versucht: //echo -a $dll(0) // Anzahl der geladenen DLLs anzeigen Ergebnis: 0 //echo -a $dll(tv.dll, _tv, -p(Pro7)-m(10)) / DLL laden //echo -a $dll(0) // Anzahl der geladenen DLLs anzeigen Ergebnis: 1 Das heisst sie müsste geladen sein, warum ein erneuter aufruf zum crash führt dürfte wohl an mIRC liegen(?). Danke nochmal für die Hilfe. Sollte doch noch ein Fehler auftreten, poste ich es in 24 Stunden :mrgreen: |
Re: C++ -> Delphi
Zitat:
|
Re: C++ -> Delphi
Das Problem liegt darin, dass du nicht einen Typ, sondern einen Pointer auf den Typ übergeben bekommst. :)
Code:
type
TLoadinfo = packed record mVersion: DWORD; mHwnd: HWND; mKeep: BOOL; end; PLoadinfo = ^TLoadinfo; procedure LoadDll(Loadinfo: PLoadinfo); stdcall; begin ShowMessage( 'mIRC-Version: ' + IntToStr(LOWORD(Loadinfo.mVersion)) + '.' + IntToStr(HiWord(Loadinfo.mVersion)) ); end; function UnloadDll(mTimeout: Integer): Integer; stdcall; begin if (mTimeout = 1) then Result := 0; end; |
Re: C++ -> Delphi
Zitat:
Delphi-Quellcode:
ist, von der Aufrufkonvention her, das gleiche wie
procedure LoadDll(Loadinfo: PLoadInfo); stdcall;
Delphi-Quellcode:
(nur halt mit zusätzlicher Angabe, ob die Struktur les-/schreibbar ist.
procedure LoadDll(var Loadinfo: TLoadinfo); stdcall;
|
Re: C++ -> Delphi
Ich hatte es erst auch mit TLoadInfo als Parameter und es gab auch den Fehler. Mit PLoadInfo ist er weg und die Parameter werden auch korrekt übergeben.
|
Re: C++ -> Delphi
Merkwürdiger Fehler...
Bisher ging ich davon aus, dass der gleiche Code generiert wird. |
Re: C++ -> Delphi
@ste_ett: Nachdem mir die Version (mIRC 6.16) angezeigt wird bzw wenn ich auf "OK" klicke stürzt mirc ab.
|
Re: C++ -> Delphi
Guck mal per F7+Haltepunkte auf dem "begin", ob das bei dem Showmessage() passiert, oder, beim "end".
|
Re: C++ -> Delphi
hm, wie geht das? bei dlls? ich muss ja von aussen darauf zugreifen
|
Re: C++ -> Delphi
Haltepunkte kannst du setzen, in dem du links neben die codezeile klickst. Die Zeile wird dann rot unterlegt.
Für die DLL gibst du dann eine Host-Anwendung an. Start - Parameter Bei "Host-Anwendung" trägst du die mIRC.exe ein, dann kannst du die Host-Anwendung normal über F7/F9 starten. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:43 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