AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Callback Funktionen und DLL?

Ein Thema von barana · begonnen am 15. Jun 2007 · letzter Beitrag vom 15. Jun 2007
Antwort Antwort
barana

Registriert seit: 14. Apr 2007
5 Beiträge
 
#1

Callback Funktionen und DLL?

  Alt 15. Jun 2007, 16:10
Hallo Leute,

ich habe ein Pluginbasierendes Programm geschrieben und hab nun jede Menge Probleme zu bewältigen, die ich nicht einmal verstehe.
Die Plugins sind einfache Win32 DLL's.

Die DLL's besitzen nur 2 Hauptfunktionen, die mit der Delphi Standardkonvetion "register" aufegrufen werden. Die Funktionen heissen "init" und "start" und sehen wie folgt aus.

Delphi-Quellcode:
{DLL Plugin}

type
  TGet = function(link,cookie:pchar;redirect,sendcookie:boolean;
  var location,rawheaders:pchar):pchar ;stdcall;

  TPost = function(link,params,cookie:pchar;redirect,sendcookie:boolean;
  var location,rawheaders:pchar):pchar ;stdcall;
var
  CBGet : TGet ;
  CBPost : TPost ;

function initcb(const get,post:Pointer):pchar ;
begin
  @CBGet := Get ;
  @CBPost := Post ;

  Result := 'Plugin_1' ;
end;

function start(link:pchar):pchar ;
var
  Location, RawHeaders : pchar
begin
  Result := CBPost('http://www.google.de','','',false,false,Location,RawHeaders) ;
end;
Wie man sieht, übergebe ich Init 2 Zeiger auf Funktionen im Hauptprogramm.
Get dient dazu den HTML Code einer beliebigen Seite abzurufen und Post steht eben für einen Post Request zur Verfügung. Diese beiden Fukntionen werden aber mit "stdcall" als Aufrufkonvention aufgerufen, da ich glaube gelesen zu haben, dass Callbackfunktionen sich nur mit "stdcall" vertragen.

Für die echten Funktionen im Hauptprogramm habe ich Indy 9 verwendet und sie sehen folgerndermaßen aus.

Delphi-Quellcode:
{Hauptprogramm}

function PLGHTTPGet(link,cookie:pchar;redirect,sendcookie:boolean;var location,rawheaders:pchar):pchar ; stdcall ;
var
  IDHTTP : TIdHTTP ;
begin
  IDHTTP := TIdHTTP.Create(nil);
  IDHTTP.HandleRedirects := redirect ;
  if sendcookie then
  begin
    IDHTTP.AllowCookies := True ;
    IDHTTP.Request.CustomHeaders.Text := cookie ;
  end
  else
    IDHTTP.AllowCookies := False ;
  try
    Result := pchar(IDHTTP.Get(link)) ;
  except
    Result := 'failed' ;
  end;
  location := pchar(IDHTTP.Response.Location) ;
  rawheaders := pchar(IDHTTP.Response.RawHeaders.text);
  IDHTTP.Free ;
end;

function PLGHTTPPost(link,params,cookie:pchar;redirect,sendcookie:boolean;var location,rawheaders:pchar):pchar ; stdcall;
var
  Parameters : TStringList ;
  HTTP : TIdHTTP ;
begin
  HTTP := TIdHTTP.Create(nil);
  Parameters := TStringList.Create ;
  Parameters.Add(params) ;
  HTTP.HandleRedirects := redirect ;
  if sendcookie then
  begin
    HTTP.AllowCookies := True ;
    HTTP.Request.CustomHeaders.Text := cookie ;
  end
  else
    HTTP.AllowCookies := False ;
  try
    Result := PChar(HTTP.Post(link,Parameters)) ;
  except
    Result := 'failed' ;
  end;
  location := PCHar(HTTP.Response.Location) ;
  rawheaders := pChar(HTTP.Response.RawHeaders.text);
  Parameters.Free ;
  HTTP.Free ;
end;
Die DLL Plugins fasse ich in einem array mit einem Record zusammen und rufe sie nacheinander auf.
Delphi-Quellcode:
{Hauptprogramm} 
  ..
  ...
  try
    MemoOutput.text := PlgArray[i].start(PChar(Link)) ;
  except
  ...
  ..
Soweit sogut.
Es klappt auch alles wunderbar und wird auch richtig ausgeführt, aber dann passieren unter bestimmten Umständen ganz komische Sachen.
Wenn ich die Post Funktion ca. 20 - 30 in einem Plugin aufrufe, dann bekommt das Hauptprogramm nichts mehr als Ergebnis von "start" zurück, obwohl in der DLL alles richtig ablaüft und sie auch das richtige Result zurückgibt.
Dann wird es aber noch abgefahrener und das Hauptprogramm bleibt nach dem Aufruf der DLL einfach sporadisch an irgendeiner Stelle hängen.

Jetzt kann ich es mir absolut nicht erklären.
Es kommt auch nie eine AV, aber manchmal ein Runtime Error.

Könnt ihr einen Fehler entdecken.
Mache ich vielleicht grundsätzlich etwas falsch?

Danke im Voraus.

PS: Ich benutze Delphi 2006.
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#2

Re: Callback Funktionen und DLL?

  Alt 15. Jun 2007, 16:17
das liegt daran das du als result ein pchar zurück gibst!
ein PChar ist nichts anderes als ein Zeiger der eben auf das erste Zeichen einer Zeichenkette zeigt.

folgendes klappt noch (ist aber auch unschön)
result := 'staticher Text'; folgendes geht aber nicht!
result := lokaleVarible; Der Grund ist ganz einfach. PChar ist eben nur ein Pointer auf das erste Zeichen einer Zeichenkette.
Bei dem statichen Text zeigt dieser PChar auf einen fest einkompilierten Text im Speicher (der da fest drin steht).
Bei der lokalen Variblen hingegen zeigt der PChar auf das erste Zeichen der lokalen Variablen die auf dem Stack liegt. Der Stack wird aber beim verlassen der Funktion aufgeräumt und somit zeigt der Pointer auf den Stack wo eventuell schon was ganz anderes liegt wenn du diesen abfragst bzw. nichts mehr liegt.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Benutzerbild von ste_ett
ste_ett

Registriert seit: 10. Sep 2004
Ort: Dülmen
464 Beiträge
 
Delphi 7 Professional
 
#3

Re: Callback Funktionen und DLL?

  Alt 15. Jun 2007, 16:18
PChar als Rückgabewert einer DLL-Funktion kann schnell zu Fehlern führen, da zwar für die Speicheradresse des PChars Speicher reserviert wird, aber nicht für die Zeichenkette, was dazu führen kann, dass ein anderes Programm diesen Speicherbereich allokiert, und damit u.U. "deine" Daten weg sind.

Entweder sorgst du für eine eigene Speicherverwaltung für die Rückgabewerte, oder, was ich empfehlen würde, die übergibst die PChars als Var-Parameter, dann hast du auch immer den korekten Wert in deiner Funktion.
Stefan
"Geht nicht!" ist keine Fehlerbeschreibung und "Hab ich schon versucht!" keine Antwort!

Hey, it compiles! Ship it!
  Mit Zitat antworten Zitat
barana

Registriert seit: 14. Apr 2007
5 Beiträge
 
#4

Re: Callback Funktionen und DLL?

  Alt 15. Jun 2007, 16:41
Zitat von ste_ett:
Entweder sorgst du für eine eigene Speicherverwaltung für die Rückgabewerte, oder...
Aha und wie würde eine Speicherverwaltung dann aussehen?
Wieso klappt es denn mit einem oder 2 Posts einwandfrei und erst ab ca. 20 wird es erst Fehlerhaft?
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#5

Re: Callback Funktionen und DLL?

  Alt 15. Jun 2007, 16:53
eine eigene speicherverwaltung würde auch nichts bringen weil zu dem zeitpunkt wo du drauf zugreifst das ganze gar nicht mehr auf dem stack liegt bzw. du dich da nicht mehr drauf verlassen solltest.

Und warum es am anfang klappt und später nicht liegt daran das irgendwann eben dochmal was auf dem stack landet was deins überschreibt. Somit fehlt dann wohl die abschließende #0 und es wird diese gesucht. Mit etwas pech liegt diese dann außerhalb des Speichers auf den du zugriff hast und schon knallts, hängts etc.
Eine Notlösung wäre das du anstelle einer lokalen Variablen eine globale verwendest, denn diese behält ihren wert auch noch nach verlassen der Procedure da sie nicht auf dem stack liegt. Ist aber eben eine Notlösung. richtiger wäre einen PChar auf bereits reservierten speicher zu übergeben wo deine procedure dann die zeichen rein kopiert.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
barana

Registriert seit: 14. Apr 2007
5 Beiträge
 
#6

Re: Callback Funktionen und DLL?

  Alt 15. Jun 2007, 17:22
Erstmal danke für die schnellen Antworten, denn ich konnte mir dabei nichts zusammenreimen.

Jetzt übergebe ich das Ergebnis der DLL, per var Pramater zurück ans Hauptprogramm. Dies funktioniert anscheinend auch ganz gut, jedoch kann ich nun das Programm nicht mehr beenden und muss es per Takmanager killen.

Wenn ich debugge, dann erhalte ich am Ende folgende Fehlermeldung.
Zitat:
Es sind zu viele auseinanderfolgende Exceptions aufgetreten: "Zgriffsverletzung bei 0x004015db: Schreiben von Adresse 0x03477e50". Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#7

Re: Callback Funktionen und DLL?

  Alt 15. Jun 2007, 18:07
per var-parameter? den Pointer? irgendwas wirst du da durcheinander. kannst du den quelltext mal zeigen? Wenn du einen pointer auf den speicher übergibst wo hinn geschrieben werden soll (also das ergebnis) muss nichts als var-Parameter übergeben werden.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
barana

Registriert seit: 14. Apr 2007
5 Beiträge
 
#8

Re: Callback Funktionen und DLL?

  Alt 15. Jun 2007, 18:38
Na ich habe aus der start function eine procedure gemacht:

Delphi-Quellcode:
procedure start(link:pchar; var Return:pchar);
var
  Location, RawHeaders : pchar
begin
  Return:= CBPost('http://www.google.de','','',false,false,Location,RawHeaders) ;
end;
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#9

Re: Callback Funktionen und DLL?

  Alt 15. Jun 2007, 19:19
so nicht! das ist das gleiche wie mit dem PChar als result. Das musst du erstmal ändern.
Du weißt ja schon wieder die adresse der lokalen Variablen deinem PChar zu.

So macht man das:
Delphi-Quellcode:
//procedure außerhalb der dll
var
  lRes : String;
begin
  SetLength(lRes, 1024);
  ZeroMemory(@lRes[1], Length(lRes));
  DllProcedure(@lRes[1], Length(lRes));
end;

//procedure innerhalb der dll
procedure DllProcedure(ARes: PChar; AResSize);
var
  meinString: String;
begin
  meinString := 'Rückgabe';
  move(ARes^, meinString[1], Min(AResSize, Length(meinString));
end;
(ungetestet)
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#10

Re: Callback Funktionen und DLL?

  Alt 15. Jun 2007, 20:05
Guck mal hier: http://www.michael-puff.de/Developer...ring_DLL.shtml
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 07:48 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