![]() |
RPC und Delphi 2009
Tag auch,
ich hätte auch mal wieder ein Problem. Ich hatte ein Delphi 7 Programm, das einige XML-RPC Funktionen verwendet hat. ( aus xmlrpctypes, xmlrpcclient) RpcCaller : TRpcCaller; RpcFunction : IRpcFunction; RpcResult : IRpcResult; Nun läuft die Version 2.0 von XML-RPC nicht mehr mit Delphi 2009 auf die ich nun umstelle, was mich zu der Frage bringt, welche Vorgehensweise hier am sinnvollsten ist: 1. Auf andere Komponenten wechseln und wenn ja welche, oder 2. Die XML-RPC versuchen in Gang zu bringen Wäre schön, wenn mir jemand weiterhelfen könnte. Gruß |
Re: RPC und Delphi 2009
Zitat:
|
Re: RPC und Delphi 2009
Nunja, wenn ich die XML-RPC mit D2009 verwenden will nehme ich an, dass ich die auch damit kompilieren muss.
Beim kompiliervorgang kommen dann aber zahlreiche Fehler, die wohl mit der Umstellung auf Utf8 zusammenhängen. Jetzt gings mir eben darum, ob es hier eine Aktualisierung gibt, ob das mittlerweile sowieso alles anders gemacht wird, oder ob ich mich einfach zu dumm anstelle. |
Re: RPC und Delphi 2009
Dann zeig doch mal die Fehlermeldungen :zwinker:
|
Re: RPC und Delphi 2009
Zitat:
REMObjects SDK- ![]() Pros: Free .NET client (great for calling Delphi from ASP) SOAP server FreePascal support XMLRPC RealThinClient- ![]() Pros: Extemely flexible FreePascal support XMLRPC (zitiert aus: ![]() |
Re: RPC und Delphi 2009
Nuja, zum Beispiel tritt in dieser Funktion ein E2010: Inkompatible Typen - Fehler auf.
Delphi-Quellcode:
Hier stellt sich nun die Frage, ob man die Funktionen (gibts auch rückwärts, die ist aber fehlerfrei)
FUNCTION Utf8ToAnsi (Source : STRING; UnknownChar : CHAR = '¿') : ANSISTRING; // <- Result: AnsiString
(* Converts the given UTF-8 String to Windows ANSI (Win-1252). If a character can not be converted, the "UnknownChar" is inserted. *) VAR SourceLen : INTEGER; // Length of Source string I, K : INTEGER; A : BYTE; // Current ANSI character value U : WORD; Ch : CHAR; // Dest char Len : INTEGER; // Current real length of "Result" string BEGIN SourceLen := Length (Source); SetLength (Result, SourceLen); // Enough room to live Len := 0; I := 1; WHILE I <= SourceLen DO BEGIN A := ORD (Source [I]); IF A < $80 THEN BEGIN // Range $0000..$007F INC (Len); Result [Len] := Source [I]; // ---> Fehlermeldung: E2010: Inkompatible Typen: AnsiChar und Char (Source : String, Result : AnsiString) INC (I); END ELSE BEGIN // Determine U, Inc I IF (A AND $E0 = $C0) AND (I < SourceLen) THEN BEGIN // Range $0080..$07FF U := (WORD (A AND $1F) SHL 6) OR (ORD (Source [I+1]) AND $3F); INC (I, 2); END ELSE IF (A AND $F0 = $E0) AND (I < SourceLen-1) THEN BEGIN // Range $0800..$FFFF U := (WORD (A AND $0F) SHL 12) OR (WORD (ORD (Source [I+1]) AND $3F) SHL 6) OR ( ORD (Source [I+2]) AND $3F); INC (I, 3); END ELSE BEGIN // Unknown/unsupported INC (I); FOR K := 7 DOWNTO 0 DO IF A AND (1 SHL K) = 0 THEN BEGIN INC (I, (A SHR (K+1))-1); BREAK; END; U := WIN1252_UNICODE [ORD (UnknownChar)]; END; Ch := UnknownChar; // Retrieve ANSI char FOR A := $00 TO $FF DO IF WIN1252_UNICODE [A] = U THEN BEGIN Ch := CHR (A); BREAK; END; INC (Len); Result [Len] := Ch; // ---> Fehlermeldung: E2010: Inkompatible Typen: AnsiChar und Char (Ch : Char , Result : AnsiString) END; END; SetLength (Result, Len); END; überhaupt noch benötigt. Hab mich mit dem Code noch nicht eingehend befasst, wollte das eben auch möglichst vermeiden. Aber anscheinend sind alle Äpfel sauer, in die ich hier beissen kann. @mjustin: Danke mal für die Alternativen Allerdings kommen beide für mich nicht in Frage, da der Einsatz sich auf einige wenige Zugriffe beschränkt und der Preis somit kaum zu rechtfertigen ist. |
Re: RPC und Delphi 2009
String / Char -> Ansistring/AnsiChar
|
Re: RPC und Delphi 2009
Wenn das alles wäre, wäre mir das schon klar. Mir geht es aber eher darum ob das Gesamtkonzept in dieser Form noch funktioniert.
Wenn ich einen Char hier mit einem AnsiChar ersetze, zieht sich das wie ein Rattenschwanz durch den ganzen Code. Der Aufwand den kompletten XML-RPC Code zu durchforsten wird dann doch relativ groß. |
Re: RPC und Delphi 2009
Zitat:
Aber das mit dem Rattenschwanz stimmt schon ... |
Re: RPC und Delphi 2009
Okay, hab mich jetzt mal an den Rattenschwanz gewagt und fröhlich Ansis erschlagen.
Hänge nun aber an einem Punkt in der Datei XmlRpcClient an dem die Funktion
Delphi-Quellcode:
aufgerufen wird.
HashMessageDigest := TIdHashMessageDigest5.Create;
try { determine the md5 digest hash of the request } Hash := Hash128AsHex(HashMessageDigest.HashValue(XmlRequest)); // <- Jetzt bin ich mir nicht ganz sicher ob ich mich hier schon verrant habe. Eine Methode Hashvalue konnte ich in HashMessageDigest samt aller Mutter, Grußmutter ... -Klassen nicht finden. Mit allen anderen vorhandenen Methoden hauts auch nicht hin. Hash128ToHex will einen Übergabewert vom Typ T4x4LongWordRecord. Aus Indy's IdHashMessageDigest:
Delphi-Quellcode:
Das einzige Attribut das diesen Typ aufweist ist FState in der Mutterklasse TIdHashMessageDigest4 und liegt protected vor.
T4x4LongWordRecord = array[0..3] of LongWord;
Edit: HashValue gibt es allerdings in den Klassen TIdHash16 und TIdHash32 die genau wie die TIdHashMessageDigests von TIdHash erben ... :coder2: |
Re: RPC und Delphi 2009
Delphi-Quellcode:
Indy muss auf jeden Fall auf die neue Tiburon-Version upgedated werden, aber der XML-RPC Code scheint etwas älter zu sein.
HashMessageDigest := TIdHashMessageDigest5.Create;
try { determine the md5 digest hash of the request } Hash := Hash128AsHex(HashMessageDigest.HashValue(XmlRequest)); // <- Es gibt aber auch in der neuen Indy Version MD5 Funktionen, die den gewünschten Hash liefern sollten. Nur heissen sie jetzt wahrscheinlich anders. Meine Indy-basierte MD5 Funktion sieht so aus:
Delphi-Quellcode:
function MD5Hash(const Input: WideString): string;
begin with TIdHashMessageDigest5.Create do try Result := LowerCase(HashStringAsHex(string(Input))); finally Free; end; end; |
Re: RPC und Delphi 2009
Joa, mit deiner MD5 Funktion kompiliert es, allerdings wirft Indy (idHTTP) bei der Ausführung Fehler.
Wärs gelaufen hätte ich mich gefreut wie'n Schnitzel, aber so müsste ich jetzt doch tiefer in die Thematik einsteigen, als ich das eigentlich wollte. Da die mMn größte Problematik hier der verwendete XML-Parser ist, der nur begrenzte Unicode Unterstützung mitbringt, muss man sich wohl damit mal genauer auseinandersetzen, bzw. einen adäquaten Ersatz finden. PS: Wenn jemand natürlich den Stein der Weisen zu diesem Thema parat hat ... :wink: |
Re: RPC und Delphi 2009
Liste der Anhänge anzeigen (Anzahl: 1)
So hab jetzt doch noch mal versucht was Vernünftiges zu Stande zu bringen,
bin aber nach erfolgreichem Kompilieren wieder an der Ausführung gescheitert: EIdHttpProtocolException HTTP/1.0 500 Internal Error The server encountered an unexpected condition which prevented it from fulfilling the request. Unter Delphi 7 mit XML-RPC-2.0.0 funktioniert das ganze mit dem selben Aufruf ohne Probleme. In LibXmlParser.pas hab ich folgende Änderungen vorgenommen (Alle Änderungen im Code durch Note (SeHa-2009-04-23) gekennzeichnet) - Die AnsiToUtf8 und Utf8ToAnsi Funktionen auskommentiert - Special Helper Functions rausgenommen, da die zu Fehlern geführt haben. - TranslateEncoding schleift nur noch durch:
Delphi-Quellcode:
In XmlRpcCommon.pas:
FUNCTION TXmlParser.TranslateEncoding (CONST Source : STRING) : STRING;
BEGIN Result := Source; END; - IdHashMessageDigest eingebunden - Funktion eingefügt: function HashStringMD5AsHex(const AStr: WideString): string; welche der Funktion von mjustin entspricht In XmlRpcClient.pas: - Bekannte benötigte Änderungen für Indy10 eingesetzt - In TRpcCaller.Execute HashStringMD5AsHex Funktion eingesetzt
Delphi-Quellcode:
In XmlRpcServer.pas:
{ determine the md5 digest hash of the request }
// Hash := Hash128AsHex(HashMessageDigest.HashValue(XmlRequest)); Hash := HashStringMD5AsHex(XmlRequest); - IdContext eingebunden - Bekannte benötigte Änderungen für Indy10 eingesetzt DiMime.pas: durch aktuellere Version ersetzt Wie gesagt, hat es nach den Änderungen kompiliert (Auch ohne dass Ansi-Strings und -Chars ersetzt wurden) Aber bei der Ausführung kommt besagter Fehler. Hab das ganze Gedönz mal angehängt. |
Re: RPC und Delphi 2009
Ab heute gibt es den
![]() Hiermit sollte sich dann das leidige Thema RPC auf D2009 vernünftig lösen lassen. (Edit: Wodurch dann für mich auch die Änderungsversuche am XML-RPC hinfällig werden) |
Re: RPC und Delphi 2009
hatte mir grad mal dieses XML-RPC angesehn und sowas find ich schon witzig ... wozu haben die da XML-Klassen verwaut, wo sie nichtmal genutzt werden? :shock:
Delphi-Quellcode:
nja, und den darin verwendeten LibXmlParser hatte ich auch noch nicht so richtig unter D09 zum Laufen gebracht.
function TRpcFunction.GetRequestXML: string;
var Strings: TStrings; begin Strings := TStringList.Create; try Strings.Add('<?xml version="1.0"?>' + #13#10); Strings.Add('<methodCall>' + #13#10); Strings.Add(' <methodName>' + FObjectMethod + '</methodName>' + #13#10); GetBodyXML(Strings); Strings.Add('</methodCall>' + #13#10); Result := Strings.Text; finally Strings.Free; end; end; |
Re: RPC und Delphi 2009
Jo, ich hatte mich etwas darin verrannt den Parser umschreiben zu wollen,
woran ich gescheitert bin. Dann wollte ich den Parser ersetzen, bin aber nach gottseidank nur kurzer Versuchszeit heute auf die Nachricht beim RTC gestoßen. Jetzt versuch ich mich mal daran. |
Re: RPC und Delphi 2009
Also einen in D09 laufenden Parser hab ich ja ... nur kenn ich mich mit diesem RPC nicht so aus und da wäre es schwer nun etwas dafür zu machen,
wobei der Aufbau der XML-Dateien schonmal recht einfach gestaltet ist. Wie nutzt man es denn programmseitig? |
Re: RPC und Delphi 2009
Die Antwort wird dir wahrscheinlich nicht sehr viel bringen, da ich zur komplizierten Seite, dem Server leider gar nichts sagen kann,
da das ein Kollege in Python geschrieben hat. Der Aufruf auf Client-Seite ist simpel, da nur die Eigenschaften EndPoint, ObjectMethod sowie Ip-Adresse und Port benötigt werden. Beispiel-Aufruf: Das Programm würde hier eine Beschreibung zu einem Item anhand seiner ItemID aus einer serverseitig hinterlegten Liste holen. (Wie gesagt, die eigentliche Logik steckt dabei im Serverprogramm.)
Delphi-Quellcode:
(**********************************
** Function: RPC_ItemDescription ** **********************************) function RPC_ItemDescription (IP_Address: String; TCP_Port, ItemID : Integer):LongInt; var RpcCaller : TRpcCaller; RpcFunction : IRpcFunction; RpcResult : IRpcResult; begin RpcCaller := TRpcCaller.Create; try RpcCaller.EndPoint := '/RPC2'; RpcCaller.HostName := IP_Address; RpcCaller.HostPort := TCP_Port; RpcFunction := TRpcFunction.Create; RpcFunction.ObjectMethod := 'get_item_descr'; RpcFunction.AddItem (ItemID); RpcResult := RpcCaller.Execute(RpcFunction); Result := RpcResult.AsInteger; finally RpcCaller.Free; end; end; |
Re: RPC und Delphi 2009
Also im Prinzip wird nur eine XML-Datei zusammengebastelt,
wo ein Funktionsname und Parameter eingetragen werden. Dann wird das via TCPIP an eine IP+Port versendet, man bekommt eine neue XML-Datei zurück und sucht da das Ergebnis raus. Also im eigenem Programm werden keine Funktionen aufgerufen? Na da sollte sich ja, wenn die Parameter nicht all zu aufwändig und Exotisch ausfallen, was mit einer kleinen Klasse machen lassen. :stupid: Müßte ich nur mal sehn, wie ich das mit dem Internetversand hinbekomm. |
Re: RPC und Delphi 2009
Joa, möglich, dass das nicht allzu komplex ist, wenn man sich da allerdings ohne XML Vorwissen reinwirft,
kann das schnell ganz schön viel werden. :gruebel: Das Problem dabei ist nur, dass das ganze XML-RPC kompatibel bleiben muss, da das eben in nahezu jeder Sprache verfügbar ist. Edit: Wie gesagt, Mit Delphi 7 war die Sache für mich mit Aufrufen der gezeigten Größenordnung erledigt. Mit dem Thema selbst musste ich mich da nicht allzu sehr befassen. Meine gescheiterten Versuche mit dem Parser haben mir dann eher Frust als Lust bereitet. |
Re: RPC und Delphi 2009
für die XML selber dürfte es reichen sie ohne Codierinfo zu erstellen, dann wäre sie per Standard UTF-8-kodiert und das dürfte mit der Ansi- bzw. ASCII-Kodierung vereinbar sein, welche dieses nicht mehr funktionierende XML-RPC-Teil verwendet ... steht leider nirgends, welches es genau ist, aber egal.
Da sie es nicht angeben und XML laut den XML-Spezifikationen standardmäßig UTF-8 ist, wär das vermutlich dennoch OK. Und die ![]() Nja, mal sehn was ich da hinbekomm. |
Re: RPC und Delphi 2009
Zitat:
Du solltest aber beachten, dass die RTC Lizenz in diesem Jahr öfter gewechselt wurde als manche Leute ihre Unterwäsche wechseln... |
Re: RPC und Delphi 2009
So, ich hab mich jetzt mal am RTC versucht, was auch im Ansatz funktioniert, solange ich keine Parameter mit senden muss.
Ich habs aber bisher nicht geschnallt, wie ich Parameter richtig übergeben kann.
Delphi-Quellcode:
with RtcHttpClient do begin
ServerAddr := AnsiString(IP_Address); ServerPort := AnsiString(IntToStr(TCP_Port)); // UseWinHTTP := True; Connect; end; with RtcClientModule do begin ModuleFilename := '/RPC2'; ModuleHost := AnsiString(IP_Address); DataFormat := fmt_XMLRPC; StartCalls; Data.NewFunction('get_item_descr'); (* --> hier möchte ich noch die Variable Integer: ItemID als Parameter übergeben *) Call(RtcResult); Post; end; with RtcResult do begin if Valid then Result := 1 else Result := 0; end; |
Re: RPC und Delphi 2009
Okay, sollte jetzt laufen.
Benutzt wurden: XMLDocument: TXMLDocument; RtcHttpClient: TRtcHttpClient; RtcDataRequest: TRtcDataRequest;
Delphi-Quellcode:
Alle anderen Kombinationen die ich ausprobiert hatte, haben mir immer die XML Daten so verbaut,
(******************************
** Function: RPC_GetItemDesc ** ******************************) function RPC_GetItemDesc(IP_Address: String; TCP_Port, ItemID: Integer):LongInt; begin with XMLDocument do begin Active := true; Version := '1.0' ; Encoding := 'UTF-8' ; ChildNodes.Clear; with AddChild('methodCall') do begin with AddChild('methodName') do NodeValue:= 'get_item_descr'; with AddChild('params') do with AddChild('param').AddChild('value').AddChild('int') do NodeValue:= ItemID; end; end; with RtcHttpClient do begin ServerAddr := AnsiString(IP_Address); ServerPort := AnsiString(IntToStr(TCP_Port)); UseWinHTTP := True; Connect; end; with RtcDataRequest do begin Request.Method := 'Post'; Request.URI := '/RPC2'; Post; end; end; (****************************************** ** Procedure: RtcDataRequestBeginRequest ** ******************************************) procedure RtcDataRequestBeginRequest(Sender: TRtcConnection); begin with TRtcDataClient(Sender) do begin Request['Content-type']:='text/xml'; Write(AnsiString(XMLDocument.XML.Text)); end; end; dass der Server die Anfragen nicht gefressen hat. Mit dieser Kombination tut nun alles wie es soll. |
Re: RPC und Delphi 2009
Hier ist ein Beispiel wie es auch mit der eingebauten XML-RPC funktionalität gehn sollte ...
Benutzt werden: RtcHttpClient: TRtcHttpClient; RtcClientModule: TRtcClientModule; RtcResult: TRtcResult;
Delphi-Quellcode:
Da RTC SDK komponenten event-basierts sind, kommt das resultat in das OnResult event von der RtcResult komponente.
with RtcHttpClient do begin
ServerAddr := AnsiString(IP_Address); ServerPort := AnsiString(IntToStr(TCP_Port)); // UseWinHTTP := True; AutoConnect:=True; end; with RtcClientModule do begin ModuleFilename := '/RPC2'; ModuleHost := AnsiString(IP_Address); DataFormat := fmt_XMLRPC; with Data.NewFunction('get_item_descr') do // <methodcall><methodname> with newArray('params') do // <params> asInteger[0]:=123; // <param><value><int> Call(RtcResult); // <- raus damit end; Übrigens ... die "Data.toXMLRPCRequest" funktion kann mann vor dem "Call()" beutzen um zu testen wie das XML-RPC string aussieht das an den Server geschickt wird. MfG, Danijel Tkalcec |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:17 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