AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi DLL Callback Pointerübergabe erwartet Variable
Thema durchsuchen
Ansicht
Themen-Optionen

DLL Callback Pointerübergabe erwartet Variable

Ein Thema von Cyberaxx · begonnen am 28. Okt 2007 · letzter Beitrag vom 2. Nov 2007
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    
Benutzerbild von Cyberaxx
Cyberaxx

Registriert seit: 15. Jul 2005
311 Beiträge
 
Delphi XE5 Professional
 
#1

DLL Callback Pointerübergabe erwartet Variable

  Alt 28. Okt 2007, 02:51
Hallo,

stehe hier gerade vor dem kleinen Problem das ich versuche in einer DLL eine Callback Funktion zu realisieren.
Die DLL steht auch bereits nur der Aufruf der Prozedur funktioniert nicht. Bekomme immer die Meldung das eine Variable fehlen würde.
Delphi-Quellcode:
unit Defines;

interface

type
  TCallBackProc = procedure(Command: Integer); stdcall;
  TGetName = function: Pchar; stdcall;
  TGetVersion = function: PChar; stdcall;
  TSetCallBackProc = procedure(CallBackProc: Pointer); stdcall;
  TGetData = function(Command: Integer): Boolean; stdcall;
  TInit = function: Boolean; stdcall;
  TStart = procedure; stdcall;
  TStop = procedure; stdcall;
  TConfigure = procedure; stdcall;

implementation

end.
Die DLL
Delphi-Quellcode:
library TestPlugin;

uses
  SysUtils,
  Classes,
  Dialogs,
  Defines in '..\Shared\Defines.pas';

var
  FCallBackProc: TCallBackProc;

{$E mcp}

{$R *.res}

// Procedure zum testen der CallBack Funktion
procedure FTimerTimer(Sender: TObject);
begin
  if Assigned(FCallBackProc) then
    FCallBackProc(1);
end;

// Name des Plugins
function GetName: PChar; stdcall
begin
  Result := 'Media Center TestPlugin';
end;

// Version des Plugins
function GetVersion: Pchar; stdcall
begin
  Result := '1.0.0.0';
end;

// CallBack aufruf festlegen
procedure SetCallBackProc(CallBackProc: Pointer); stdcall
begin
  @FCallBackProc := CallBackProc;
end;

// Befehl empfangen
function GetData(Command: Integer): Boolean; stdcall
begin
  ShowMessage(Format('Received Command: %d -> Running CallBack', [Command]));
  FTimerTimer(nil);
end;

// Initialisieren des Plugins / Hier soll auch mal das CallBack rein
function Init: Boolean; stdcall
begin
  ShowMessage('Called Init');
end;

// Plugin Starten
procedure Start; stdcall
begin
  ShowMessage('Called Start');
end;

// Plugin Stoppen
procedure Stop; stdcall
begin
  ShowMessage('Called Stop');
end;

// Plugin konfigurieren
procedure Configure; stdcall
begin
  ShowMessage('Called Configure');
end;

exports
  GetName, GetVersion, SetCallBackProc, GetData, Init, Start, Stop, Configure;

begin
end.
Die Main
Delphi-Quellcode:
unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, JvExStdCtrls, JvListBox, JvDialogs, Defines;

type
  TForm1 = class(TForm)
    OpenDialog: TJvOpenDialog;
    JvListBox1: TJvListBox;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure DLLAufruf(Command: Integer);
  private
    Lib: THandle;
    PluginGetName: TGetName;
    PluginGetVersion: TGetVersion;
    PluginSetCallBackProc: TSetCallBackProc;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
begin
  if Opendialog.Execute then begin
    Lib := LoadLibrary(PChar(OpenDialog.FileName));

    if Lib = 0 then
      ShowMessage('Plugin konnte nicht geladen werden!');

    @PluginGetName := GetProcAddress(Lib, 'GetName');
    Self.JvListBox1.Items.Add('Name: ' + PluginGetName);

    @PluginGetVersion := GetProcAddress(Lib, 'GetVersion');
    Self.JvListBox1.Items.Add('Version: ' + PluginGetVersion);
    end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  if Lib <> 0 then begin
    @PluginSetCallBackProc := GetProcAddress(Lib, 'SetCallBackProc');
    PluginSetCallBackProc(@DLLAufruf); // Hier kommt die Meldung Variable benötigt
    end;
end;

procedure TForm1.DLLAufruf(Command: Integer);
begin
  ShowMessage(Format('Command von DLL: %d', [Command]));
end;

end.
Was habe ich falsch gemacht? es wird doch nur ein Pointer übergeben, in der DLL scheints ja zu funktionieren...
Daniel
Das Aufwachen aus einem boesen Traum muss einen nicht erleichtern. Es kann einen auch erst richtig gewahr werden lassen, was man Furchtbares getraeumt hat, vielleicht sogar welcher furchtbaren Wahrheit man im Traum begegnet ist!
  Mit Zitat antworten Zitat
Benutzerbild von Dani
Dani

Registriert seit: 19. Jan 2003
732 Beiträge
 
Turbo Delphi für Win32
 
#2

Re: DLL Callback Pointerübergabe erwartet Variable

  Alt 28. Okt 2007, 04:42
Hallo!

Kannst du statt   TSetCallBackProc = procedure(CallBackProc: Pointer); stdcall; nicht folgendes machen? TSetCallBackProc = procedure(CallBackProc: TCallBackProc); stdcall; Mit untypisierten Zeigern hast du doch nur Ärger.


Vielleicht scheitert's auch daran, dass TForm1.DllAufruf eine Klassenmethode ist. Schau mal ob's klappt, wenn du die Prozedur aus der Klasse herausnimmst.
Dani H.
At Least I Can Say I Tried
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: DLL Callback Pointerübergabe erwartet Variable

  Alt 28. Okt 2007, 07:02
Ganz wichtig! Immer zwischen "einfachen" Funktionen bzw. Prozeduren und Methoden (Funktionen in Klassen) unterscheiden. Methoden bestehen nicht nur aus einem Pointer wie Funktionen, sondern aus zwei (Da kommt nämlich noch "self" hinzu)

Also entweder du schreibst:
PluginSetCallBackProc(@Tform1.DLLAufruf); //erstmal für die Vollständigkeit Dann aber auch
Delphi-Quellcode:
TCallBackProc = procedure(Command: Integer) of object; stdcall; //jetzt ist es eine Methode
TSetCallBackProc = procedure(CallBackProc: TCallBackproc); stdcall;
Oder du machst aus der Methode DLLAufruf eine Funktion, wenn es dein Konzept erlaubt.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von Cyberaxx
Cyberaxx

Registriert seit: 15. Jul 2005
311 Beiträge
 
Delphi XE5 Professional
 
#4

Re: DLL Callback Pointerübergabe erwartet Variable

  Alt 28. Okt 2007, 12:59
Nachdem ich das TForm1 davor gesetzt hatte, hat es geklappt.
Nun stehe ich aber vor einer AV.

Delphi-Quellcode:
// Procedure zum testen der CallBack Funktion
procedure FTimerTimer(Sender: TObject);
begin
  if Assigned(FCallBackProc) then
    FCallBackProc(1);
end;
Er springt auch in meine Main App, so wie er es sollte, nur dort ist das Command irgendeine Zahl, aber nicht der Wert den ich übergeben habe.
Danach kommt eine Zugriffsverletzung.

Zitat:
---------------------------
Debugger Exception Notification
---------------------------
Project Testanwendung.exe raised exception class EAccessViolation with message 'Access violation at address 00000001. Read of address 00000001'. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------
Was habe ich da nun wieder verbockt? Wenn ich aus dem CallBack das Command ganz heruas nehme klappt es ohne Probleme.
Hier stellt sich dann auch die Frage, was ist besser den CallBack einfach nur so aufzurufen und sich aus der DLL dann erst den Command zu holen oder ihn eben mit zu übergeben?

Es sollen ja keine Speichermanager verwendet werden.

[edit]Den CallBack Teil hatte ich von hier. http://www.delphipraxis.net/internal...t=dll+callback
[/edit]
Daniel
Das Aufwachen aus einem boesen Traum muss einen nicht erleichtern. Es kann einen auch erst richtig gewahr werden lassen, was man Furchtbares getraeumt hat, vielleicht sogar welcher furchtbaren Wahrheit man im Traum begegnet ist!
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#5

Re: DLL Callback Pointerübergabe erwartet Variable

  Alt 28. Okt 2007, 13:08
Was ist denn TForm1.DllAufruf eigentlich? Eine Prozedur mit der Signatur Procedure(Self: TObject; Command: integer);
So, die Dll erwartet aber, dass sie eine Prozedur mit der Signatur Procedure(Command: integer); stdcall; erhält. Zuerst einmal ist im Formular die Aufrufkonvention eine ganz andere. Die Dll schiebt den Parameter auf den Stack, aber dein Formular erwartet zwei Parameter in den Registern. Dadurch wird übrigens auch dein Stack zerschossen, da die Methode bei stdcall eigentlich aufräumen muss.
Zum anderen kann, selbst wenn die Aufrufkonvention gleich ist, eigentlich nur Schrott herauskommen, da die Dll andere Parameter übergibt als die Routine erwartet.
Des Weiteren musst du dich einfach mal entscheiden, ob du jetzt Methoden oder Prozeduren verwenden willst. Wenn du Methoden willst, dann musst du der Dll auch die Instanz übergeben, an der die Methode aufgerufen wird, denn ein Methodenzeiger besteht einmal aus dem Prozedurzeiger und aus Self. Also müsstest du dann Form1.Dllaufruf übergeben.
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Benutzerbild von Cyberaxx
Cyberaxx

Registriert seit: 15. Jul 2005
311 Beiträge
 
Delphi XE5 Professional
 
#6

Re: DLL Callback Pointerübergabe erwartet Variable

  Alt 28. Okt 2007, 14:01
PluginSetCallBackProc(@Tform1.DLLAufruf); //erstmal für die Vollständigkeit Dieses habe ich doch bereits benutzt, damit funktioniert es ja auch.

So jetzt ist die AV weg aber immernoch ein falscher Wert... setze ich wieder wo falsch an?

DLL
Delphi-Quellcode:
var
  FCallBackProc: TCallBackProc;

{$E mcp}

{$R *.res}

// CallBack aufruf festlegen
procedure SetCallBackProc(CallBackProc: Pointer); stdcall
begin
  @FCallBackProc := CallBackProc;
end;

// Befehl empfangen
procedure GetData(Command: Integer); stdcall
begin
  ShowMessage(Format('Received Command: %d -> Running CallBack', [Command]));

  if Assigned(FCallBackProc) then
    FCallBackProc(101);
end;
Main
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    OpenDialog: TJvOpenDialog;
    JvListBox1: TJvListBox;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    JvEdit1: TJvEdit;
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
// procedure DLLAufruf(Command: Integer);
    procedure Button4Click(Sender: TObject);
  private
    Lib: THandle;
    PluginGetName: TGetName;
    PluginGetVersion: TGetVersion;
    PluginSetCallBackProc: TSetCallBackProc;
    PluginGetData: TGetData;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure DLLAufruf(Command: Integer);
begin
  ShowMessage(Format('Command von DLL: %d', [Command]));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if Opendialog.Execute then begin
    Lib := LoadLibrary(PChar(OpenDialog.FileName));

    if Lib = 0 then
      ShowMessage('Plugin konnte nicht geladen werden!');

    @PluginGetName := GetProcAddress(Lib, 'GetName');
    Self.JvListBox1.Items.Add('Name: ' + PluginGetName);

    @PluginGetVersion := GetProcAddress(Lib, 'GetVersion');
    Self.JvListBox1.Items.Add('Version: ' + PluginGetVersion);
    end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  if Lib <> 0 then begin
    @PluginSetCallBackProc := GetProcAddress(Lib, 'SetCallBackProc');
    PluginSetCallBackProc(@DLLAufruf);
    end;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  @PluginGetData := GetProcAddress(Lib, 'GetData');
  PluginGetData(StrtoInt(Self.JvEdit1.Text));
end;

end.
Ich bekomme als CallBack Command nur eine 1, es sollte aber 101 sein...
Daniel
Das Aufwachen aus einem boesen Traum muss einen nicht erleichtern. Es kann einen auch erst richtig gewahr werden lassen, was man Furchtbares getraeumt hat, vielleicht sogar welcher furchtbaren Wahrheit man im Traum begegnet ist!
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#7

Re: DLL Callback Pointerübergabe erwartet Variable

  Alt 28. Okt 2007, 14:12
Du solltest in TSetCallBackProc den Parameter als TCallbackProc deklarieren (wie es schon Dani vorgeschlagen hat), dann würde nämlich ein aussagekräftiger Fehler kommen, in etwa "Incompatible types: 'Calling conventions differ'".
Zitat:
Zuerst einmal ist im Formular die Aufrufkonvention eine ganz andere. Die Dll schiebt den Parameter auf den Stack, aber dein Formular erwartet zwei Parameter in den Registern. Dadurch wird übrigens auch dein Stack zerschossen, da die Methode bei stdcall eigentlich aufräumen muss.
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Benutzerbild von Cyberaxx
Cyberaxx

Registriert seit: 15. Jul 2005
311 Beiträge
 
Delphi XE5 Professional
 
#8

Re: DLL Callback Pointerübergabe erwartet Variable

  Alt 28. Okt 2007, 14:16
Habs von Pointer auf TCallBackProc abgeändert, jedoch kommt kein Fehler und ich erhalte immernoch die 1 im CallBack...
Daniel
Das Aufwachen aus einem boesen Traum muss einen nicht erleichtern. Es kann einen auch erst richtig gewahr werden lassen, was man Furchtbares getraeumt hat, vielleicht sogar welcher furchtbaren Wahrheit man im Traum begegnet ist!
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#9

Re: DLL Callback Pointerübergabe erwartet Variable

  Alt 28. Okt 2007, 14:27
Du musst es auch in TSetCallbackProc ändern, denn daran orientiert sich ja dein Hauptprogramm.
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Benutzerbild von Cyberaxx
Cyberaxx

Registriert seit: 15. Jul 2005
311 Beiträge
 
Delphi XE5 Professional
 
#10

Re: DLL Callback Pointerübergabe erwartet Variable

  Alt 28. Okt 2007, 14:38
Ah ok.... Hatte da noch nen @ sitzen. nun kommt der Fehler auch.

Zitat:
Incompatible types: 'Calling conventions differ'
Aber warum nun der Fehler? das ist doch beides nun eine Prozedur von Command: Integer;
mein DLLAufruf hängt ja nun auch nicht mehr direkt in der Klasse?

Versteh das nun nicht ganz.

Eigentlich soll es eine DLL werden die den IO-Warrior ansteuert um den IR-Receiver zu nutzen.
Wenn dieser ein Signal der Fernbedienung erhällt, sollte er mittels Callback das dem Programm mitteilen.

Wichtig für mich ist eben das ich das alles nicht nur auf Delphi eingrenze...
Daniel
Das Aufwachen aus einem boesen Traum muss einen nicht erleichtern. Es kann einen auch erst richtig gewahr werden lassen, was man Furchtbares getraeumt hat, vielleicht sogar welcher furchtbaren Wahrheit man im Traum begegnet ist!
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 4  1 23     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 23:21 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