![]() |
Auf Fehlerrückgabe prüfen
Hallo,
ich habe ein Designproblem bei meiner Gestaltung meines Quelltextes: Ich habe ein API Klasse zu Steuerung eines Gerätes entworfen, die kann u.a. folgendes:
Delphi-Quellcode:
die Methoden geben einen Fehlercode zurück:
TGeraet.GetUhrzeit(var uhrzeit:TUhrzeit):integer;
TGeraet.GetParamter(var paramter:Word):integer; TGeraet.GetSeriennummer(var sn:string):integer; 0 -> kein Fehler 120 -> Timeout 130 -> Checksum Error... Nun finde ich es irgendwie blöd jedes mal wenn ich eine Methode aufrufe dieses zu machen
Delphi-Quellcode:
da ich sehr viele Kommunikationsanfragen habe und das ganze meinen Quelltext aufquellt :-(
if (meinGeraet.GetSeriennummer(sn) <>0) then
begin // Fehlerbehandlung end; ... if (meinGeraet.GetUhrzeit(uz) <>0) then begin // Fehlerbehandlung end; Danke vielleicht wisst ihr ja eine vielleicht auch OOP-Design-Lösung Gruß DelphiManiac |
Re: Auf Fehlerrückgabe prüfen
dann gib anstelle des Integers einen Bool zurück und den Feherlode als optionalen Parameter. Oder den Fehlercode im Bool (ein Bool kann schließlich nicht nur 1 und 0 sein) wobei der Bool dann genau das umgekehrte Ergebnis ist.
mit dem optionalen Fehlercode würde es so aussiehen
Delphi-Quellcode:
function TGeraet.GetUhrzeit(var uhrzeit:TUhrzeit; AResultCode: PInteger=nil):Boolean;
begin [...] if Assigned(AResultCode) then ResultCode^ := bisherigerRueckgabewert; result := bisherigerRueckgabewert = 0; end; |
Re: Auf Fehlerrückgabe prüfen
Vielleicht hilft dir die Aufrufkonvention SAFECALL.
|
Re: Auf Fehlerrückgabe prüfen
Du kannst ja auch Exceptions verwenden.
|
Re: Auf Fehlerrückgabe prüfen
@sirius: Was mach den genau die Aufrufkonvention SAFECALL?
@Dezipaitor: wie genau würdest du sowas mit Exceptions lösen? würdest du eine Exception werfen? Thx |
Re: Auf Fehlerrückgabe prüfen
Wenn du Exception werfen kannst, ist das doch das einfachste. Falls das nicht geht, dann arbeite mit SafeCall (ist ja auch das, was man u.U. bei Interfaces macht)
Ich dachte du hattest Exception schon ausgeschlossen, aber wenn nicht, dann nimm lieber diesen Weg. Exceptions:
Delphi-Quellcode:
Beim Aufrufen:
interface
type UhrzeitException=class(Exception); //... und noch andere Exceptions implementation function TGeraet.GetUhrzeit:TUhrzeit; begin //... if Fehler then raise UhrzeitException.create('wenn du magst, dann hier noch ein Text'); end;
Delphi-Quellcode:
try xyz:=meingeraet.getuhrzeit; //...andere Abfragen except on UhrzeitException do Uhrzeitfehler on ... do ... //... else raise; end; |
Re: Auf Fehlerrückgabe prüfen
@sirius: ich glaube der Fragesteller ist wie ich davon ausgegangen das du die CallingConvention SaveCall meintest. Und das würde ja keinen wirklichen Sinn machen?! Denn das würde ja nur bestimmen wie die Parameterübergabe erfolgt (in welcher Reihenfolge, ob über Register etc.).
|
Re: Auf Fehlerrückgabe prüfen
@SirThornberry:
Ja genau, die Parameterübergabe ist hier ja schon geregelt, und da gibt es auch keine Vorschriften. Mir ging es nur darum einen auftretenden Fehler zu melden und diesen abzuhandeln. Und vorallendingen wollte ich nicht immer den Rückgabewert prüfen müssen bei jedem Funktionsaufruf... Muss zugeben, ich nutze Exceptions viel zu selten, ist es denn hier generell sinvoll eine Exception zu werfen, wie verhält sich denn das Programm, wenn ich in meiner Funktion erkenne, dass ein Fehler vorlag, und dann eine Exception auslöse? Gruß |
Re: Auf Fehlerrückgabe prüfen
@Sir: Das ist auch richtig. SAFECALL hat aber neben der Angabe über Parameterübergabe etc. auch noch einen weiteren Hintergrund. Eine SafeCall-Funktion hat immer zwei Rückgabewerte (eine Prozedur dementsprechend immer einen), zum einen das "echte Ergebnis", zum anderen einen Fehlercode.
Hintergrund ist der, dass man in der OOP ja keine Klassen kreuz und quer durch verschiedene Adressbereiche bzw. Speichermanager etc. schieben kann. Konkret (wobei ... jetzt bin ich mir nicht 100% sicher): Du kannst keine Klasse in einer Library erstellen und in deiner Main-Exe freigeben (ohne Sharemem etc.). Bei Exceptions (in OOP) würde genau das passieren. Beim Werfen der Exception wird die Klasse erstellt und hinterm nächsten except gekillt. -->CRASH Dagegen gibts SafeCall: Du machst die Exceptionbehandlung innerhalb der Bibliothek und gibst neben dem eigentlichen Ergebnis auch einen Fehlercode mit zurück. Der Compiler prüft nach dem Aufruf einer SafeCall-Funktion automatisch den Fehlercode und ruft gegebenenfalls die Funktion in der Variablen SafeCallErrorProc auf (die normalerweise nil ist). Ausserdem wirft er erneut eine SafeCallException. Das ist das besondere an SafeCall und entspricht so ziemlich dem was DelpiManiac als Funktionsköpfe hatte. Also eine Funktion
Delphi-Quellcode:
ist dasselbe wie
function xyz(a,b,c,...:integer; var result:integer):TErrorCode; stdcall;
Delphi-Quellcode:
vom Header her (mit TErrorCode=integer)
function xyz(a,b,c,...:integer):integer; safecall;
So, und jetzt wirds dirty (vielleicht gehts auch einfacher, aber Delphi übergibt sonst immer denselben Fehlercode):
Delphi-Quellcode:
Und im Hauptprogramm:
//Die Funktion in einer Bibliothek
function test(var erg:integer):cardinal;stdcall; //hier allerdings lieber stdcall, weil wir wollen ja den ErrorCode selber setzen const Error=$80000000; //Vorzeichenbit muss gesetzt sein für Fehler begin //der eigentliche Funktionsinhalt erg:=-5; //wenn Fehler dann result:=120+error; //120 unser Fehlercode //sonst result:=0; //hauptsache nicht negativ end;
Delphi-Quellcode:
Soweit, so gut. Und irgendwo vorher muss noch
var ExceptionType:integer;
procedure SafecallError; asm //die ersten beiden Zeilen nutzen wenn keine Exception geworfen werden soll //pop ecx //mov [esp],edx //Ergebnis in Exceptiontype schreiben and eax,$7FFFFFFF mov ExceptionType,eax end; procedure TForm1.Button1Click(Sender: TObject); var mytest:function:integer;safecall; begin mytest:=@test; try edit1.Text:=inttostr(mytest); except on ESafeCallException do edit1.text:=inttostr(Exceptiontype); else raise; end; end;
Delphi-Quellcode:
gesetzt werden.
safecallerrorProc:=@SafeCallError;
War hier nur so ne Idee...die auch erstmal funktioniert :mrgreen: Edit: Wenn man in SafeCallError alle auskomentierten Zeilen so lässt, geht es auch ohne ASM:
Delphi-Quellcode:
procedure safecallerror(ErrorCode:integer;NonExceptionAddr:pointer);
begin ExceptionType:=Errorcode and $7FFFFFFF; end; |
Re: Auf Fehlerrückgabe prüfen
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:20 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 by Thomas Breitkreuz