首页 > 代码库 > 用 Lazarus 开发 OPC Client 1 (关于字符集)

用 Lazarus 开发 OPC Client 1 (关于字符集)

其实很早就打算在Lazarus里面做一个,要么在实际应用中时间太紧需要使用OPC了就用Delphi的程序改改,也就用了。

到了FPC3.0之后也就lazarus1.6以后,其核心对UTF8的全面支持,导致Delphi的很多程序都不能直接转移到Lazarus里面。明知山有虎偏向虎山行,OPC里面会大量用到PWideChar和OleVariant这是难点,本身技术上倒不是,但与Lazarus的融合就存在很多不不确定性。

OPC客户端的构建流程很简单

  1. 建立ActiveX服务器的引用
  2. 通过服务器接口的“组管理器”——构建组
  3. 通过组的条“目管理器”在该组添加“条目”,也就是工业领域说的“标签”——Tag
  4. 现在可以Read/Write读写标签了
  5. 如果希望效率,OPC提供的托管方式,也就是常常翻译为“订阅”的方法。以组为单位构建“订阅”。
  6. 如果成功将实现 OnChange 、AsyncRead、AsyncWrite (异步读写)。

期间每一步都要注意资源的释放!而且每一步又都要与字符串打交道,注意COM内部大量使用WideString,但微软的大师在设计自然是会大量用到指针的,所以PWideChar与FPC的String的交互就成了主要任务。关键问题字符串,不彻底解决就算构建成功也不能正常显示,更何况由于Lazarus的内部转换,基本就是构建不成功。

RTL,LCL默认都是UTF8这是有优势的,但很难驾驭,这也导致很多lazarus1.2x之前的很多解决方案失效,比如SysToUTF8和UTF8ToSys,跟踪发现

function UTF8ToSys(const s: string): string;begin  {$IFDEF UTF8_RTL}  Result:=s;  {$ELSE}  if NeedRTLAnsi and (not IsASCII(s)) then    Result:=UTF8ToAnsi(s)  else    Result:=s;  {$ENDIF}end;注意这里面的条件编译{$IFDEF UTF8_RTL} 

导致这些过程\函数\方法有时候“生效”有时候“无效”主要是条件编译{$IFDEF UTF8_RTL}的作用,其实上次发的博文提到的FPC 3.0 增加-dDisableUTF8RTL项目编译选项,使参数保存在本项目里面。当配置完毕以上语句就可以执行到{$ELSE} 部分了。

整个现象这个让我懊恼了好久好久,总是不能明确结果,导致Lazarus程序字符串输出不能达到预期的效果,用了好多方法,甚至怀疑是否真的该放弃当时自己写的UTF8转换单元,使用系统自带功能的判断。幸好手头有两个项目一个有这个参数一个没有,结果导致截然不同的效果,当然有一个能准确实现设计意图否则也就不会去分析了——庆幸。最后还是看了[Lazarus] UTF8 RTL for Windows才想起。

方向明确了之后,要解决问题自然就是找出具体的办法处理字符串。

我们对待POleChar通常的解决办法是 PWchar(WideString(XXXstring));在Lazarus里面小工程例子项目没有问题,大了,也就是资源使用比较多也许到用的时候早就释放了。就必须用到StringToOleStr(XXXstring)了。

整合后得到如下过程函数

function UTF8StrToOleStr(const Source: UTF8String): PWideChar;var  vS: string;begin  vS     := UTF8ToSys(Source);  // Result := POleStr(WideString(vS));  Result := StringToOleStr(vS);  if Result = nil then    Result := ‘‘;end;function OleStrToUTF8Str(const Source: PWideChar): UTF8String;var  vS: string;begin  if Source = nil then    Result := ‘‘  else    WideCharToStrVar(Source, vS);  Result := SysToUTF8(vS);end;

现在记性太不好了,做个记录。

用 Lazarus 开发 OPC Client 1 (关于字符集)