Einzelnen Beitrag anzeigen

Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.680 Beiträge
 
Delphi 5 Professional
 
#7

AW: Unicode und WideChar API-Funktionen

  Alt 4. Apr 2023, 20:02
Bitte entschuldigt die längere Funkstille meinerseits. Die vergangenen Tage hab ich damit verbracht, einen Teil meiner Units für Free Pascal umzuschreiben. Leider sind die Ergebnisse alles andere als zufriedenstellend. Die Sache ist so undurchsichtig und stellenweise widersprüchlich, dass bei mir einige Fragen aufgetaucht sind und ich die Hoffnung habe, dass jemand sie eindeutig beantworten kann.
  • Nehmen wir diese Funktion aus source\rtl\objpas\sysutils\sysutils.inc:
    Delphi-Quellcode:
    function GetModuleName(Module: HMODULE): string;
    var
      ResultLength, BufferLength: DWORD;
      Buffer: UnicodeString;
    begin
      BufferLength := MAX_PATH div 2;
      repeat
        Inc(BufferLength, BufferLength);
        SetLength(Buffer, BufferLength);
        ResultLength := GetModuleFileNameW(Module, Pointer(Buffer), BufferLength);
        if ResultLength = 0 then
          Exit('');
      until ResultLength < BufferLength;
      SetLength(Buffer, ResultLength);
      Result := Buffer;
    end;
    Warum wird hier ein UnicodeString an einen String (laut Hint in der Lazarus IDE ist String = AnsiString) zugewiesen? Während der Umstellung meiner Units sind mir noch andere Funktionen aufgefallen, die nach demselben Prinzip arbeiten.

    Aus Interesse hab ich die Funktion unverändert in meine Projektdatei kopiert (und umbenannt), und wie erwartet wird die Zuweisung an Result mit der entsprechenden Warnung bemängelt. Andererseits steht im Wiki-Artikel, dass man eine solche Zuweisung machen kann - dort string an UnicodeString, aber das Prinzip bleibt - und der Compiler sich um die Konvertierung kümmert:
    Zitat:
    When a parameter type is a pointer PWideChar, you need a temporary UnicodeString variable. Assign your String to it. The compiler then converts its data.
    Entweder ist die Warnung Banane und die Konvertierung erfolgt sauber, oder die Warnung ist berechtigt und die Zuweisung führt potentiell zu Datenverlust. Beides ist unbefriedigend, letzteres sogar fatal. Was ist richtig?

  • Was passiert bei einem direkten (harten) Cast von UnicodeString nach String, vor allem mit enthaltenen Unicode-Zeichen außerhalb der eigenen ANSI-Codepage? Werden die Zeichen verstümmelt oder landet das zweite Byte des Zeichens unverändert im (Ansi)String? Kommen die Zeichen wieder sauber heraus, wenn ein UnicodeString an einen String und dieser danach wieder an einen UnicodeString zugewiesen wird, oder sind die Zeichen danach kaputt?
  • Anschließend an den vorherige Punkt: Sollte ich Casts benutzen oder Konvertierungsfunktionen?
  • Sofern die Antwort auf die vorherige Frage "Konvertierungsfunktionen" lautet, sollte ich die Unit LazUnicode verwenden oder könnte ich auch simple Funktionen wie die im Thema Delphi7 mit nur einer Unit Unicode fähig machen zu findenden benutzen? Wenn Unit LazUnicode, sollte ich UseUTF16 definieren/verwenden oder nicht?

    Wobei ich mich schon frage, wozu die Unit LazUnicode gut sein soll, wenn doch der Compiler (laut Wiki) die Konvertierung durchführt... Wie schon gesagt, es ist undurchsichtig.

  • Apropos Free Pascal Wiki. Dort ist der Satz zu finden
    Zitat:
    There is also a test program LazUnicodeTest in components/lazutils/test directory.
    Im ganzen Verzeichnis von Lazarus gibt es keine Datei mit einem solchen Namen. Nach einiger Sucherei hab ich das gemeinte Projekt gefunden unter components\lazutils\examples\LazUnicode\LazUnicode Console.lpi.
    Im Wiki steht zuvor noch der Satz
    Zitat:
    Currently the {$ModeSwitch UnicodeStrings} can be tested by defining "UseUTF16".
    Also dachte ich, ich geh in den Projektoptionen meines Projekts zu "Custom Options" > Defines und setze dort UseUTF16. Hat keine Wirkung. Ist meine Annahme falsch, dass die dort definierten Defines für alle Units des Projekts gelten?

    Erst nach dem Auffinden des Test-/Beispielprojekts konnte ich sehen, dass UseUTF16 dort im Bereich "Additions and Overrides" der Projektoptionen definiert wird. Solche Ungenauigkeiten bzw. fehlerhafte Angaben nerven und sind für Neulinge in Lazarus bzw. Free Pascal nicht gerade förderlich.
Es gibt noch Klassen und Funktionen (TIniFile, TFileStream, FormatDateTime, AnsiQuotedStr), für die ich keine unicodefähigen Varianten gefunden habe bzw. Konvertierungsmöglichkeiten brauche.

Grüße
Dalai
  Mit Zitat antworten Zitat