Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Leerstring bei Interface (https://www.delphipraxis.net/215211-leerstring-bei-interface.html)

Maekkelrajter 28. Mai 2024 12:37

Leerstring bei Interface
 
In einem Projekt mache ich ausgiebig Gebrauch von dem Itunes COM Interface, um von meinem Programm aus die Itunes-Software 'fernsteuern' zu können. Das funktioniert i. d. R. problemlos. Laut der 'iTunes COM Interface Documentation' sind Strings als 'BSTR' deklariert, die ja mit dem 'Widestring' von Delphi kompatibel sind. Das Auslesen dieser Strings ist kein Problem, eine Zuweisung zu einem solchen String normalerweise auch nicht. Nur wenn ich einen solchen String 'löschen' will, indem ich einen Leerstring zuweise, gibt es eine Delphi-Exception 'EOleException Ungültiger Zeiger'.
In der Typelibrary 'iTunesLib_TLB' ist z. B. der String 'EpisodeID' folgendermaßen deklariert:
Delphi-Quellcode:
// *********************************************************************//
// Interface: IITFileOrCDTrack
// Flags:    (4432) Hidden Dual OleAutomation Dispatchable
// GUID:     {00D7FE99-7868-4CC7-AD9E-ACFD70D09566}
// *********************************************************************//
  IITFileOrCDTrack = interface(IITTrack)
    ['{00D7FE99-7868-4CC7-AD9E-ACFD70D09566}']
[...]  
    function Get_EpisodeID: WideString; safecall;
    procedure Set_EpisodeID(const EpisodeID: WideString); safecall;
[...]
    property EpisodeID: WideString read Get_EpisodeID write Set_EpisodeID;
[...]
  end;
Bisher habe ich mich damit beholfen, dass ich anstatt eines Leerstrings (EpisodeID := '') einen Nullwert übergebe (EpisodeID := #0).
Dadurch verschwindet der Eintrag zwar in der Listenansicht, aber in der Itunes - Datenbank bzw. der daraus generierten XML-Datei steht nach wie vor ein 'leerer' String mit der Länge 1: <key>EpisodeID</key><string> </string>.
Mit einem VB-Script funktioniert die Zuweisung eines Leerstrings (track.EpisodeID="") dagegen erwartungsgemäß: Der Eintrag wird komplett entfernt.
Ich habe leider wenig Erfahrung mit Interfaces unter Delphi. Ist es generell unzulässig, einen Leerstring zuzuweisen, oder geht das irgendwie ganz anders? Oder handelt es sich um einen Fehler der Type-Libraray?
Als Workaround könnte ich aus meinem Programm ein VB-Script starten, aber das wäre wirklich nur eine Notlösung.
Es wäre schön, wenn mir da jemand weiterhelfen könnte.

Gruß LP

Uwe Raabe 28. Mai 2024 13:07

AW: Leerstring bei Interface
 
Eigentlich sollte das kein Problem sein, aber vielleicht hilft es, den Leerstring als lokale Konstante anzulegen und diese dann zuzuweisen:
Delphi-Quellcode:
procedure ClearTrack(track: IITFileOrCDTrack);
const
  EmptyString = '';
begin
  track.EpisodeID := EmptyString;
end;

Maekkelrajter 28. Mai 2024 13:27

AW: Leerstring bei Interface
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1537242)
Eigentlich sollte das kein Problem sein, aber vielleicht hilft es, den Leerstring als lokale Konstante anzulegen und diese dann zuzuweisen:
Delphi-Quellcode:
procedure ClearTrack(track: IITFileOrCDTrack);
const
  EmptyString = '';
begin
  track.EpisodeID := EmptyString;
end;

Das hatte ich auch schon probiert. Funktioniert leider auch nicht :(

Gruß LP

Olli73 28. Mai 2024 14:52

AW: Leerstring bei Interface
 
Auf nil setzen?

Uwe Raabe 28. Mai 2024 15:58

AW: Leerstring bei Interface
 
Zitat:

Zitat von Olli73 (Beitrag 1537246)
Auf nil setzen?

Ein WideString ist nicht zuweisungskompatibel mit nil. Allerdings kann man das mit einem Trick in diesem Fall bewerkstelligen:
Delphi-Quellcode:

  track.Set_EpisodeID(PWideString(nil)^);
Aber ich würde mich nicht wundern, wenn das auf dasselbe hinausläuft wie der Leerstring.

himitsu 28. Mai 2024 16:29

AW: Leerstring bei Interface
 
Ehrlich gesagt, versteh ich nicht, warum '' oder sonstwo aus irgendwelchen typisierten oder untypisierten Konstanten/Variablen.
Selbst wenn es der falsche String-Typ ist, dann konvertiert Delphi das automatisch.

ACHTUNG: Variant vs. OleVariant

Im Variant können Delphi-Typen enthalten sein, wie z.B. AnsiString und String/UnicodeString,
womit fremde Sprachen natürlich nicht zurechtkommen, da sie das nicht kennen.

Der OleVariant ist ein OLE-kompatibler Variant, welcher ausschließlich Typen enthalten kann, welche OLE kennt, da sie dort definiert wurden.

Also entweder OleVariant verwenden,
oder ihr müsst eine typisierte Konstante benutzen (WideString oder OleVariant), mit dem passenden Typen, welchen OLE kennt.
Delphi-Quellcode:
const EmptyString: WideString = '';

[edit] war grad gedanklich bei einem anderen Probleme, was hier vor einer Weile im Forum war, auch mit einem OLE-Interface.






Auch zu beachten: Die SysUtils kennt ebenfalls ein Delphi-Referenz durchsuchenEmptyStr.
Und ich würde es als gefährlich einstufen diese Konstante zu benutzen.
  • erstmal kann der Kompiler nicht mehr optimieren (
    Delphi-Quellcode:
    if S = '' then
    wird zu
    Delphi-Quellcode:
    if Pointer(S) = nil then
    optimiert)
    und bei
    Delphi-Quellcode:
    if S = EmptyStr then
    wird System._UStrEqual aufgerufen
  • dann sind typisierte Konstanten eigentlich nur schreibgeschützte Variablen (der Schreibschutz ist aber nicht wirklich vorhanden)
    im Delphi XE war dieser Bereich des Arbeitsspeichers nicht schreibgeschützt
  • und ich finde Code damit auch nicht wirklich schnell lesbar ... denke da immer an eine Variable, aber bei
    Delphi-Quellcode:
    ''
    seh ich sofort das "LEER".

Code:
if S = '' then
004E63CB 837DF800         cmp dword ptr [ebp-$08],$00
004E63CF 7507             jnz $004e63d8

Unit1.pas.31: if S = EmptyStr then
004E63D8 8B45F8           mov eax,[ebp-$08]
004E63DB 8B15DC514F00     mov edx,[$004f51dc]
004E63E1 8B12             mov edx,[edx]
004E63E3 E8BC4DE3FF      call $0031b1a4
004E63E8 7507             jnz $004e63f1
Wir hatten z.B. mal den Spaß, dass diese Konstante ausversehn überschrieben wurde, mit dem Wert
Delphi-Quellcode:
'Empty'
,
und da DevExpress in seinem QuantumGrid überall diese Konstante verwendet, standen dann in allen leeren Zellen (mit NULL) plötzlich ÜBERALL "Empty" drin.

Maekkelrajter 28. Mai 2024 22:52

AW: Leerstring bei Interface
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1537248)
Delphi-Quellcode:

  track.Set_EpisodeID(PWideString(nil)^);
Aber ich würde mich nicht wundern, wenn das auf dasselbe hinausläuft wie der Leerstring.

Fast dasselbe. Damit gibt's eine Exception der Klasse $C0000005 mit der Meldung 'access violation at 0x013f9a80: read of address 0x00000000' aufgetreten'.
So geht's also offenbar auch nicht :(

Gruß LP

himitsu 28. Mai 2024 23:08

AW: Leerstring bei Interface
 
Es ist das Selbe.
Abgesehn von ShortString's ist ein leerer String per se ein NIL.

Theoretisch wäre es möglich, dass es auch nicht nil ist, mit der Length=0, aber grundsätzlich kommt sowas eigentlich nie vor.

Andere Ausnahme ist PChar(''), welches nicht NIL zurück gibt, sondern einen Zeiger auf einen Speicher, wo zwei #0 drin stecken. (was mache API nicht mag)



Kann es sein, dass hier IMMER eine ID reingegeben werden MUß, womit ein Leerstring quasi verboten ist?

Ist deine Interface-Instanz überhaupt OK?
(IITFileOrCDTrack)




Sicher, dass es wirklich safecall ist?



$C0000005 = Fatal + AccessViolation
0x00000000 = z.B. NIL

0x013f9a80 = was ist hier?
Beim Debuggen ein Strg+Alt+M und dann schauen, wo dieses drin ist (also was die nächst kleinere Basisadresse besitzt)

uligerhardt 29. Mai 2024 07:16

AW: Leerstring bei Interface
 
Zitat:

Zitat von Maekkelrajter (Beitrag 1537243)
Zitat:

Zitat von Uwe Raabe (Beitrag 1537242)
Eigentlich sollte das kein Problem sein, aber vielleicht hilft es, den Leerstring als lokale Konstante anzulegen und diese dann zuzuweisen:
Delphi-Quellcode:
procedure ClearTrack(track: IITFileOrCDTrack);
const
  EmptyString = '';
begin
  track.EpisodeID := EmptyString;
end;

Das hatte ich auch schon probiert. Funktioniert leider auch nicht :(

Gruß LP

Schuss ins Blaue: Vielleicht eine Variable statt einer Konstanten?

Kas Ob. 29. Mai 2024 09:04

AW: Leerstring bei Interface
 
Liste der Anhänge anzeigen (Anzahl: 1)
Well it could be helpful and insightful if you can share a small memory dump for the data pointed by that EpisodeID, use the debugger and capture a screenshot of that address content and most importantly few bytes before it like 4 (if it is BSTR for real) like this
Anhang 56874

Anyway, from reading this :
https://learn.microsoft.com/en-us/pr...p/automat/bstr

Can you try SysFreeString and see if that clear the string without problem ?
https://learn.microsoft.com/en-us/wi...-sysfreestring


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:58 Uhr.
Seite 1 von 2  1 2      

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