Results 1 to 10 of 16

Thread: UNICODESTRING vs ANSISTRING

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    FreePascal is also moving toward String = UnicodeString, *but* you have to enable it with {$unicodestrings
    That would break backward compatibility with fpc 2.6.4, though, so you should include a check like
    Code:
    {$if (FPC_FULLVERSION<30000)} 
      {$fatal Your Free Pascal is too old! Use 3.0 or newer.}
    {$endif}
    My advice would be to define your own AllegroString and use it everywhere, the definition itself wrapped in conditionals for different compilers/platforms.

    I did that with TFileNameString and kept working on my engine long before I made final decision what format I want for the file names. Initially I was planning TFileNameString to be Utf8String on Linux and UnicodeString on Windows but I later decided it to be Utf8String everywhere. I only had to correct the type definition and conversion functions like FileNameToUtf8/FileNameToUnicode and so on, themselves having several variants wrapped in conditionals.

    P.S. Abstraction layers are good.

  2. #2
    PGDCE Developer de_jean_7777's Avatar
    Join Date
    Nov 2006
    Location
    Bosnia and Herzegovina (Herzegovina)
    Posts
    287
    I also do what Chebmaster does. Define my own StdString type which is currently UnicodeString, and convert in abstract platform routines. In your case your own type would be ansistring due to the Allegro library.
    Existence is pain

  3. #3
    Thanks for the advices.

    Quote Originally Posted by Chebmaster View Post
    My advice would be to define your own AllegroString and use it everywhere, the definition itself wrapped in conditionals for different compilers/platforms.
    Quote Originally Posted by de_jean_7777 View Post
    I also do what Chebmaster does. Define my own StdString type which is currently UnicodeString, and convert in abstract platform routines. In your case your own type would be ansistring due to the Allegro library.
    Actually I defined two types for Allegro.pas yet: AL_STR which is ANSISTRING, and AL_STRptr which is PCHAR (or PANSICHAR depending the compiler). That solves part of the problem.

    It is using Delphi's RTL where I have problems. For example, to draw the score on screen I may use this:
    Code:
      al_draw_text (aFont, aColor, aXpos, aYpos, 0, Format ('SCORE: %d', [aScore]));
    This works perfect in FPC but shows a warning in Delphi. Note that it actually renders the text (except in a few Allegro functions) but the warning is pretty annoying. I know I can avoid it using conversion functions as I've explained above but they aren't needed by FPC (actually they'll not work!).

    Quote Originally Posted by pitfiend View Post
    I think you can define some compile time arguments. Those that controls how strings are managed.
    $X+ $X- Extended Syntax, this one makes Delphi strings PChar compatible. Also allows you to use functions as procedures ignoring results
    $H+ $H- Long Strings, this one turns on/off UnicodeString. Can be used locally to set strings to old Delphi behavior.
    $V+ $V- This one is useful with shortstrings only as it allows you to give any sized strings as parameter when set as $V-. If you set it to $V+ then you need to pass strict string types.
    This are mainly backward compatibility options. Be careful, unexpected results may happen.

    Another trick you can use, is to define a local string type after detecting if Delphi or Free Pascal, and use it as you need in every parameter you pass.
    I didn't know about $X and $V arguments. Anyway I did some testing and I didn't find they helps.

    The test I did was:
    Code:
      procedure TForm1.Button1Click (Sender: TObject);
      VAR
        lText: ANSISTRING;
      begin
        INC (fNum);
        lText := 'Test #%d';
        lText := Format (lText, [fNum]);
        Memo1.Lines.Add (lText)
      end;
    Compiled with {$H-}, and also changing the "Long strings by default" to false, but it still shows the warning.

    I think I should add conditional compilation in the examples (they're only a few that conficts) or write different examples for FPC and Delphi for such cases.
    No signature provided yet.

  4. #4
    PGDCE Developer de_jean_7777's Avatar
    Join Date
    Nov 2006
    Location
    Bosnia and Herzegovina (Herzegovina)
    Posts
    287
    Quote Originally Posted by Ñuño Martínez View Post
    I know I can avoid it using conversion functions as I've explained above but they aren't needed by FPC (actually they'll not work!).
    You can add your own functions which do conversion when Delphi is used, but just return the string as is when FPC is used, via conditional compilation. They do the required thing within them, and just use them consistently instead of Delphi specific functions. Define them in a shared unit. I do this for different platforms. I don't use Delphi, but I have seen other code which does something similar in order to support both Delphi and FPC.
    Existence is pain

  5. #5
    I think you have something there. Thanks. I think I'll do it that way.
    No signature provided yet.

  6. #6
    Quote Originally Posted by Ñuño Martínez View Post
    The test I did was:
    Code:
      procedure TForm1.Button1Click (Sender: TObject);
      VAR
        lText: ANSISTRING;
      begin
        INC (fNum);
        lText := 'Test #%d';
        lText := Format (lText, [fNum]);
        Memo1.Lines.Add (lText)
      end;
    Compiled with {$H-}, and also changing the "Long strings by default" to false, but it still shows the warning.
    Using your example in modern Delphi versions will always show a warning regardless of what string compiler directives you use in your code. Why? That is because the Format function is always returning default Delphi string type which is WideString, And since you are then assigning it to AnsiString you get a warning.

    So you either need to create your own version of Format function that will be returning AnsiString result or disable of using of LongString as default string type at Project Options->Building->Delphi Compiler->Compiling (check Syntax options section).
    http://docwiki.embarcadero.com/RADSt...o/en/Compiling
    Do note that this affects your entire project so if you have other code parts that are built to work with Unicode string they may stop working properly.

  7. #7
    Thanks for your comments.

    After some working, I've reduced a lot the warnings when compiling. I'm still doing testing and changes trying to reach zero warnings (if possible).

    I've also added my own Format function as SilverWarrior suggested and I think I'll add functions to convert from/to numeric values too.

    Once done I'll release a new beta version so you can test it. If you're curious you can see what I'm doing here.
    Last edited by Ñuño Martínez; 21-02-2020 at 11:01 AM. Reason: Add link
    No signature provided yet.

  8. #8
    Sorry for the double post, but I have to say this: the solution was trivial

    While testing I discovered that function StrPas (used internally to force some callings to overloaded functions in my abstraction layer unit) were in a different unit in modern Delphi (AnsisString instead of SysUtils), so I added it to be used only in Delphi. Since then warnings appeared again and I was like WTF Delphi is trolling me... But using the Find declaration command to see the actual declaration of Format I discovered AnsiString also defines it's own version using ANSISTRING instead of UNICODESTRING!

    Note it doesn't avoid the need of the abstraction layer unit, but it simplifies a lot the implementation of this unit (and avoids to call an extra function internally in other units). For example:
    Code:
      USES
      {$IFDEF ISDELPHI2009ANDUP}
      { This unit implements sysutils using ANSISTRING instead of UNICODESTRING,
        which is the default in modern Delphi compilers. }
        AnsiStrings;
      {$ELSE}
        sysutils;
      {$ENDIF}
    
    ··· 
    
      FUNCTION al_str_format (CONST Fmt: AL_STR; CONST Args : ARRAY OF CONST)
        : AL_STR;
      BEGIN
        Format (Fmt, Args)
      END;
    This way there's no need of conditional compilation outside Allegro.pas.

    So, now we know.
    Last edited by Ñuño Martínez; 21-02-2020 at 11:58 AM.
    No signature provided yet.

  9. #9
    Wait Delphi has a special unit just for dealing with ANSI strings? I must shamefully admit that I didn't knew that

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •