如何序列化包含静态数组(char)的记录 - 解决RTTI问题

时间:2015-11-26 10:37:31

标签: delphi delphi-xe2 rtti

我需要能够通过两个不同的接口传递相同的结构集(基本上是不同记录的数组)

第一个(遗留)工作需要一个指向记录和记录大小的指针

我正在尝试开发的第二个是类型安全的,并且需要使用每个字段的Get / Set方法设置单个字段

现有代码使用记录(可能大约100左右),内存管理在第三方DLL中处理(即我们将记录指针和大小传递给它,它处理新记录的内存管理)。

我最初的想法是将内存管理带入我的应用程序,然后复制API调用上的数据。使用旧接口这很容易,因为我只需要能够访问SizeOf()和指向我内部TList中保存的记录结构的指针。为新的类型安全接口编写适配器时出现问题

由于这些记录依赖于已知大小,因此大量使用array 0..n of char静态数组,但是当我尝试通过2010风格的RTTI访问这些时,我会收到错误消息,指出“RTTI信息不足”可用于支持此操作'。标准Delphi字符串可以工作,但旧的短字符串不起作用。不幸的是,修复字符串长度对于旧式界面正常工作很重要。我已经看过第三方解决方案,比如SuperObject和MorMot中的流媒体,虽然他们不能做任何开箱即用的事情,但这并没有给我太多希望解决方案不需要大量的重新工作。< / p>

我希望能够做的是以下内容(目前无法访问我的Delphi VM,因此不是完美的代码,但希望您能获得要点):

type
  RTestRec = record
    a : array [0..5] of char;
    b : integer;
  end;

// hopefully this would be handled by generic <T = record> or passing instance as a pointer
procedure PassToAPI(TypeInfo: (old or new RTTI info); instance: TestRec)
var
  Field: RTTIField;
begin
  for Field in TypeInfo.Fields do
  begin
    case Field.FieldType of
      ftArray: APICallArray(Field.FieldName, Field.Value);
      ftInteger: APICallInteger(Field.FieldName, Field.Value.AsInteger);
      ...
  end;
end;

被称为:

var
  MyTestRec: RTestRec;
begin
  MyTestRec.a := 'TEST';
  MyTestRec.b := 5;
  PassToAPI(TypeInfo(TestRec), MyTestRec);
end;
  • 可以通过编译器标志或类似方式强制缺少RTTI(我觉得这样一厢情愿!)
  • 旧式和新型RTTI的混合可以帮助吗?
  • 我能否以不同方式声明数组以提供RTTI但仍具有旧式流媒体所需的大小限制?
  • 从记录转到课程会有帮助吗? (我想我需要将自己的流式传输写入ArrayOfByte来处理旧接口)
  • 使用属性的hacky解决方案是否有帮助?也许存储一些丢失的RTTI信息?但是,感觉有点像是一个长期维护问题。

0 个答案:

没有答案