0

    有繁体语言包后连接ftp还是乱码 lazarus交叉编译

    2023.05.17 | admin | 267次围观

    文章目录

    (一)概念

    说到Pascal语言,除了很早的Turbo Pascal,大家通常都是用的Delphi系列。

    在Delphi7那个无比辉煌的年代过后,它就被微软的.net引入了低谷。(就是那个微软,还无间道了诺基亚)。

    它的公司·Borland·几经被收购,现在属于Embarcadero,目前进化成了一个跨平台全方位的开发工具。

    听起来不错,但是Pascal语言也从20多年前占据半壁江上,

    变成了现在使用率极小,和VB差不多,归类“其它”的开发语言。

    相信很多公司都只购买过Delphi7,后面的软件升级换代是否只能迁移到C++、Java、Golang了?

    当然不是,除了Delphi7的Object Pascal,现在还有Free Pascal和它的编译器,以及IDE可供选择。

    (1.1)Lazarus

    官网

    Lazarus 是一个兼容 Delphi 的跨平台集成开发环境,用于快速应用程序开发。

    它有多种可供使用的组件和一个图形表单设计器,可以轻松创建复杂的图形用户界面。:

    (1.2)Free Pascal

    官网

    Free Pascal 是一个成熟的、通用的、开源的 Pascal 编译器。 —— (FPC)

    它可以针对许多处理器架构:Intel x86(16 位和 32 位)、AMD64/x86-64、PowerPC、PowerPC64、SPARC、SPARC64、ARM、AArch64、MIPS、摩托罗拉 68k、AVR 和 JVM。

    支持的操作系统包括 Windows(16/32/64 位、CE 和原生 NT)、Linux、Mac OS X/iOS/iPhoneSimulator/Darwin、FreeBSD 和其他 BSD 风格、DOS(16 位或 32 位 DPMI)、操作系统 /2、AIX、Android、Haiku、Nintendo GBA/DS/Wii、AmigaOS、MorphOS、AROS、Atari TOS,以及各种嵌入式平台。

    此外,开发版还提供对 RISC-V (32/64)、Xtensa 和 Z80 架构以及 LLVM 编译器基础架构的支持。

    此外,Free Pascal 团队维护了一个将 pascal 转换为 Javascript 的转换器,称为 pas2js。

    (二)安装

    当然可以去官网下载安装包。

    懒人的话可以选择fpcupdeluxe这个工具。

    (2.1)使用fpcupdeluxe

    WIKI

    FPCUPdeluxe 是 FPC 和 Lazarus 的图形界面安装程序。 它基于 fpcup。

    它就像Python环境的Anaconda那样把分散的步骤集成到一个图形界面中。

    可以一键下载安装Lazarus+FPC的版本,并能通过快捷方式启动不同的环境。

    (2.1.1)安装Lazarus+FPC

    点击【install/update FPC+Laz】

    (2.1.2)安装交叉编译器

    第二个标签页,选需要的交叉编译类型组合,然后点击【install cross-compiler】。

    截图中可以通过日志看到,我已经下载了2个。

    PS:没想到Win64编译Win32,也属于交叉……

    (2.1.3)安装组件模块

    第三个标签页,选需要的组件/模块,然后点击【install module】。

    比如这里我下载了indy,不过重新打开后,日志似乎看不到(可到目录中查看)。

    (2.2)手动下载安装

    当然也可以全手动进行,但是我并没有:)

    请参看官网说明。

    (三)使用 (3.1)基本使用

    如果你是通过FPCUPdeluxe安装的。

    则需要用桌面快捷方式进入Lazarus。

    快捷方式内容大概如下C:\fpcupdeluxe\lazarus\lazarus.exe --pcp="C:\fpcupdeluxe\config_lazarus"。

    整个界面和Delphi差不多。

    配置使用/编写代码/调试,方式也差不多。

    旧的Delphi项目也有转换选项。

    (3.2)整体主界面

    刚安装好的Lazarus并不是上面图的样子有繁体语言包后连接ftp还是乱码

    而是更像Delphi7,各个部分的窗口是独立漂浮(undocked)的。

    如果希望界面变成一个整体的窗口,需要进入菜单【Package】->【Install/Uninstall Pacages】。

    安装下面左边3个包(没安装之前,它们会出现在右边,请搜索)。

    选择安装这三个包后,点击【Save and rebuild IDE】。

    等待编译完成并自动重启后,IDE主界面就是一体的了。

    (3.3)安装帮助文件

    官方WIKI:

    安装CHM帮助的简单总结:

    主界面上第一次按下F1,会自动帮你编译帮助的可执行文件。把下载的CHM格式的文件放入$(LazarusDir)\docs\chm目录中。

    之后就可以用帮助了。

    比如光标指向MessageDlg,按下F1,出现帮助:

    (3.4)编译模式

    新建的Lazarus项目前面有:

     {$mode objfpc}{$H+}
    

    从Delphi转换的项目前面有:

     {$MODE Delphi}
    

    区别在官方WIKI中有描述:

    但是我还是不明白,为什么在Delphi模式下:

    Format('时长: %1.2f 秒', [3.21]) 输出的却是 0.00……

    所以我都不用Delphi模式。

    (3.5)字符编码

    对于使用汉字的我们,Lazarus的字符编码情况,比Delphi复杂太多了。

    Delphi一般不需要做任何设置,会自动跟随操作系统字符集。

    只有在读取特定编码的文本文件时指定一下。

    但Lazarus有很多种情况,有意思多了……似乎也没有完美的办法。

    PS:首先记住Lazarus默认用的是UTF8编码保存源代码文件。

    (3.3.1)带LCL支持的界面程序

    这是最简单的,和Delphi一样基本上中文都能正常显示,不需要特殊处理。

    当新建一个默认的Application时有繁体语言包后连接ftp还是乱码,项目文件uses中有Interfaces

    同时在Project Inspector中能看到依赖了LCL( Lazarus Component Library):

    (3.3.2)带LCL支持的命令行程序

    但是如果你需要一个命令行程序……

    那么很遗憾,这样的程序即使不创建窗体,在没有图形UI的Linux上也是无法运行的(Windows下测试倒是可以)。

    PS:没有图形UI的Linux,指本身没有图形界面,也没有将图形界面映射到别的显示设备上,或没有图形界面支持。

    新建一个默认的Application,但不建立窗体,代码如下:

    program proTestEncoding;
    {$mode objfpc}{$H+}
    uses
      {$IFDEF UNIX}cthreads,{$ENDIF}
      {$IFDEF HASAMIGA}athreads,{$ENDIF}
      Interfaces, // this includes the LCL widgetset
      Forms;
    const
      WantLine='简体中文';
    var
      aLine:String;
    begin
      Application.Initialize;
      Write(String('请输入【简体中文】:'));
      ReadLn(aLine);
      if aLine=WantLine then
      begin
        WriteLn(String('正确。您输入的是:')+aLine);
      end
      else
      begin
        WriteLn(String('哎哟!您输入的是:')+aLine);
      end;
    end.
    

    Windows下正常:

    PS C:\fpcupdeluxe\projects> .\proTestEncoding.exe
    请输入【简体中文】:简体中文
    正确。您输入的是:简体中文
    PS C:\fpcupdeluxe\projects>
    

    WSL Linux(Ubuntu)下出错:

    $shion@shionwsl ~> /mnt/c/fpcupdeluxe/projects/proTestEncoding.linux.exe
    (proTestEncoding.linux.exe:435): Gtk-WARNING **: 11:03:16.700: cannot open display: 172.30.64.1:0
    $shion@shionwsl ~>
    

    当然,Linux下可以安装GTK支持并将UI映射到别的设备上 。

    可参考:《发现WSL(Windows Subsystem for Linux)支持GUI(图形界面)的Linux应用了》

    这时虽然我们没有建立任何窗体,但是程序正常运行了。

    $shion@shionwsl ~> /mnt/c/fpcupdeluxe/projects/proTestEncoding.linux.exe
    请输入【简体中文】:繁体中文
    哎哟!您输入的是:繁体中文
    $shion@shionwsl ~>
    

    PS:还可以弹窗呢(加入ShowMessage('XXX'))。

    但是把:Write(String('请输入【简体中文】:'));

    换成: Write('请输入【简体中文】:');

    则Windows下产生乱码。—— 现象是用GBK方式读取了UTF8编码的汉字。

    PS C:\fpcupdeluxe\projects> .\proTestEncoding.exe
    璇疯緭鍏ャ€愮畝浣撲腑鏂囥€戯細可惜
    哎哟!您输入的是:可惜
    

    而Linux没问题,原因可能是程序输出了UTF8编码的汉字,但是Windows的CMD认为程序输出的是GBK。

    但为什么String('xxxx')就正常呢。。。

    (3.3.3)普通命令行程序

    前面一节的内容似乎有点不正常……

    既然是命令行程序,那么不要LCL支持就OK了。

    不要LCL当然也不能弹窗了,纯cmd下ShowMessage('xxxx')干嘛。

    见:官方论坛10年前的讨论 (不像Delphi,它少了Application.Initialize;弹不了窗口)。

    代码变成:

    program proTestEncoding;
    {$mode objfpc}{$H+}
    uses
      classes;
    const
      WantLine='简体中文';
    var
      aLine:String;
    begin
      Write(String('请输入【简体中文】:'));
      ReadLn(aLine);
      if aLine=WantLine then
      begin
        WriteLn(String('正确。您输入的是:')+aLine);
        //ShowMessage('正确。您输入的是:'+aLine);
      end
      else
      begin
        WriteLn(String('哎哟!您输入的是:')+aLine);
        //ShowMessage('哎哟!您输入的是:'+aLine);
      end;
    end.  
    

    Windows下乱码:(猜一下,没有LCL就没法识别操作系统的编码了?,全UTF8啦?)

    顺便产生了IO错误

    PS C:\fpcupdeluxe\projects> .\proTestEncoding.exe
    璇疯緭鍏ャ€愮畝浣撲腑鏂囥€戯細可惜
    鍝庡摕锛佹偍杈撳叆鐨勬槸锛毧上?
    An unhandled exception occurred at $0000000100001847:
    EInOutError: Disk Full
      $0000000100001847
    

    Linux下正常依旧。

    (3.3.4)普通命令行程序(手动转换编码)

    既然Lazarus默认UTF8,而Windows的CMD需要Ansi(GBK)编码。

    那么就手动Utf8ToAnsi转换一下编码吧:

    Write(Utf8ToAnsi('请输入【简体中文】:'));
    

    每句都要转很麻烦

    PS:另外还可以研究一下LConvEncoding单元的CP936ToUTF8,UTF8ToCP936。

    需要依赖LazUtils(在Project Inspector中查看)

    Write(UTF8ToCP936('请输入【简体中文】:',true));
    

    (3.3.4)普通命令行程序(设置编码页)

    在程序前面设置{$codepage UTF8},

    program proTestEncoding;
    {$mode objfpc}{$H+}
    {$codepage UTF8}
    ......
    

    这样就不需要进行任何转换了

    但是根据FPC,这个选项通常不打开。

    也许这段说明没有考虑到无LCL支持的情况吧?

    麻烦的是,得处理常量字符串用,用String('XXX')转一下,否则编码还是不对……

    见官方的说明链接,如下表。

    看一眼就开始头痛了:

    (3.6)待续

    总之字符编码没找到完美的解决方案……

    继续研究……

    版权声明

    本文仅代表作者观点。
    本文系作者授权发表,未经许可,不得转载。

    发表评论