Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   C++ -> Delphi (https://www.delphipraxis.net/48205-c-delphi.html)

Pseudemys Nelsoni 22. Jun 2005 02:21


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:
type
  PLOADINFO = ^TLOADINFO;
  TLOADINFO = record
    mVersion: DWORD;
    mHwnd: HWND;
    mKeep: BOOL;
  end;
  TLoadDll = procedure(LoadInfo: PLOADINFO); stdcall;
var
  LoadDll: TLoadDll;
Leider gibts beim Aufruf eine AV, jemand ne Ahnung wie es richtig aussehen müsste? <g>

Robert Marquardt 22. Jun 2005 04:55

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.

Pseudemys Nelsoni 22. Jun 2005 11:30

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?

NicoDE 22. Jun 2005 11:46

Re: C++ -> Delphi
 
Zitat:

Zitat von Pseudemys Nelsoni
Leider gibts beim Aufruf eine AV, jemand ne Ahnung wie es richtig aussehen müsste? <g>

Es sieht richtig aus.
Zeig mal den Code der die Struktur verwendet (C und Delphi).

Pseudemys Nelsoni 22. Jun 2005 11:49

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:

Keeping a DLL Loaded after a call
By default a DLL is unloaded immediately after you make the /dll or $dll() call. You can keep a DLL loaded by including a LoadDll() routine in your DLL, which mIRC calls the first time you load the DLL:

void __stdcall (*LoadDll)(LOADINFO*);

typedef struct {
DWORD mVersion;
HWND mHwnd;
BOOL mKeep;
} LOADINFO;

mVersion contains the mIRC version number in the low and high words.

mHwnd contains the window handle to the main mIRC window.

mKeep is set to TRUE by default, indicating that mIRC will keep the DLL loaded after the call. You can set mKeep to FALSE to make mIRC unload the DLL after the call (which is how previous mIRCs worked).
Hats du da sonst noch ne Idee was ich da falsch gemacht haben könnte?


Übrigens habe ich den Methodenzeiger exportiert:

Delphi-Quellcode:
exports
  LoadDll;

NicoDE 22. Jun 2005 11:56

Re: C++ -> Delphi
 
Zitat:

Zitat von Pseudemys Nelsoni
Übrigens habe ich den Methodenzeiger exportiert

Gut, nur verstehe ich in dem Zusammenhang nicht, was der obige Code von Dir soll?
Zitat:

Zitat von Pseudemys Nelsoni
Delphi-Quellcode:
var
  LoadDll: TLoadDll;


Pseudemys Nelsoni 22. Jun 2005 11:59

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:

Robert Marquardt 22. Jun 2005 12:02

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.

NicoDE 22. Jun 2005 12:04

Re: C++ -> Delphi
 
Zitat:

Zitat von Pseudemys Nelsoni
LoadDll ist ja der Zeiger auf die Prozedur, oder? :oops:

Nope, LoadDLL ist eine implementierte Prozedur in deiner DLL. Die C-Typdefinitiondient nur als Vorlage.

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.

Pseudemys Nelsoni 22. Jun 2005 12:08

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)

Robert Marquardt 22. Jun 2005 12:18

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.

Pseudemys Nelsoni 22. Jun 2005 12:23

Re: C++ -> Delphi
 
Moin Robert,

Jo, die DLL exportiert sie:

Delphi-Quellcode:
exports
  LoadDll;
allerdings, da es sich wohl doch nicht um einen Pointer aufd eine Funktion handelt(?) ist das exportierte bereits die Funktion und daher keine(?) Variable.

NicoDE 22. Jun 2005 12:28

Re: C++ -> Delphi
 
Zitat:

Zitat von Pseudemys Nelsoni
da es sich wohl doch nicht um einen Pointer aufd eine Funktion handelt(?) ist das exportierte bereits die Funktion und daher keine(?) Variable.

Exportierte Funktions-Variable:
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;

type
  TFNLoadDll = procedure(var LoadInfo: TLoadInfo); stdcall;

var
  LoadDll: TFNLoadDll = TFNLoadDll(_LoadDll);

exports
  LoadDll;

begin
  LoadDll := _LoadDll;
end.
Exportierte Funktion:
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.
Ich gehe davon aus, dass mIRC letzteres erwartet.

Pseudemys Nelsoni 22. Jun 2005 12:36

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:
LoadDll: TFNLoadDll = TFNLoadDll(_LoadDll);
Er meint das wäre eine ungültige Typumwandlung.

NicoDE 22. Jun 2005 12:39

Re: C++ -> Delphi
 
Delphi-Quellcode:
TFNLoadDll(@_LoadDll)
würde gehen.

Geht wohl nicht *g*
Schlecht wenn man kein Delphi hat...

Pseudemys Nelsoni 22. Jun 2005 12:45

Re: C++ -> Delphi
 
Moin Nico,

hier übrigens was bei letzterer Methode passiert:

Aufruf der DLL:
http://213.39.187.106/m1.JPG

Wenn ich "OK" geklickt habe:
http://213.39.187.106/m2.JPG

Wenn ich die DLL erneut aufrufe:
http://213.39.187.106/m3.JPG

Das ShowMessage kommt daher, da ich das testweise mit in der DLL habe:

Delphi-Quellcode:
procedure LoadDll(var LoadInfo: TLOADINFO); stdcall;
begin
  LoadInfo.mKeep := True;
  ShowMessage(IntToStr(LoadInfo.mVersion));
end;
Übrigens wenn ich es so mache:

Delphi-Quellcode:
LoadDll: TFNLoadDll = TFNLoadDll(@_LoadDll);
Gibt es einen erneuten Fehler:

Zitat:

Konstantenausdruck erwartet

NicoDE 22. Jun 2005 12:50

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

Pseudemys Nelsoni 22. Jun 2005 12:59

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:

NicoDE 22. Jun 2005 13:23

Re: C++ -> Delphi
 
Zitat:

Zitat von Pseudemys Nelsoni
Das heisst sie müsste geladen sein, warum ein erneuter aufruf zum crash führt dürfte wohl an mIRC liegen(?).

Könnte an allem Möglichen liegen, Delphi-RTL, Inialization von diversen Units oder eben mIRC...

ste_ett 22. Jun 2005 13:32

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;

NicoDE 22. Jun 2005 13:41

Re: C++ -> Delphi
 
Zitat:

Zitat von ste_ett
Das Problem liegt darin, dass du nicht einen Typ, sondern einen Pointer auf den Typ übergeben bekommst. :)

Delphi-Quellcode:
procedure LoadDll(Loadinfo: PLoadInfo); stdcall;
ist, von der Aufrufkonvention her, das gleiche wie
Delphi-Quellcode:
procedure LoadDll(var Loadinfo: TLoadinfo); stdcall;
(nur halt mit zusätzlicher Angabe, ob die Struktur les-/schreibbar ist.

ste_ett 22. Jun 2005 13:53

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.

NicoDE 22. Jun 2005 13:57

Re: C++ -> Delphi
 
Merkwürdiger Fehler...
Bisher ging ich davon aus, dass der gleiche Code generiert wird.

Pseudemys Nelsoni 22. Jun 2005 14:35

Re: C++ -> Delphi
 
@ste_ett: Nachdem mir die Version (mIRC 6.16) angezeigt wird bzw wenn ich auf "OK" klicke stürzt mirc ab.

ste_ett 22. Jun 2005 16:27

Re: C++ -> Delphi
 
Guck mal per F7+Haltepunkte auf dem "begin", ob das bei dem Showmessage() passiert, oder, beim "end".

Pseudemys Nelsoni 22. Jun 2005 18:51

Re: C++ -> Delphi
 
hm, wie geht das? bei dlls? ich muss ja von aussen darauf zugreifen

ste_ett 22. Jun 2005 18:55

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