RTTI Delphi创建一个n维矩阵作为TValue

RTTI Delphi创建一个n维矩阵作为TValue,delphi,matrix,delphi-2010,rtti,tvalue,Delphi,Matrix,Delphi 2010,Rtti,Tvalue,你好 是Delphi-2010及以上RTTI功能 在我的基础上,我尝试使用递归函数来返回一个n维的TValue。矩阵(2D、3D、4D…) 例如,此过程将显示一个n维矩阵(它将n维矩阵中的所有元素列为TValue变量): 我不知道如何创建一个函数,从一个TValue创建一个n维矩阵。例如,我需要一个函数CreateDynArray(维度:整数数组;种类:TTypeKind):TValue;函数将返回一个TValue,它是一个动态数组,如何包含维度,例如: Return=CreateDynArra

你好

是Delphi-2010及以上RTTI功能

在我的基础上,我尝试使用递归函数来返回一个n维的TValue。矩阵(2D、3D、4D…)

例如,此过程将显示一个n维矩阵(它将n维矩阵中的所有元素列为TValue变量):

我不知道如何创建一个函数,从一个TValue创建一个n维矩阵。例如,我需要一个函数CreateDynArray(维度:整数数组;种类:TTypeKind):TValue;函数将返回一个TValue,它是一个动态数组,如何包含维度,例如:

Return=CreateDynArray([2,3],tkInteger);将返回TValue作为tkDynArray 如果我将显示(返回)将列出

0 0 0
0 0 0
没有终止。 我试图从一个TValue创建一个具有n维的DynArray

Procedure CreateArray(var Value:TValue; NewDimmension:integer; NewValue2Kind:TTypeKind; NewValue2:TValue; IsLast:Boolean);
var i:integer;
NewValue:TValue;
len:Longint;
begin
   If Value.IsArray then// we have components in this dimension
   begin
       for i:=0 to Value.GetArrayLength-1 do// list all
       begin
            NewValue:=Value.GetArrayElement[i];
            CreateArray(newValue,NewDimension,NewValue2Kind,NewValue2,IsLast);
            Value.SetArrayElement(i,NewValue);
       end;
   end;
end else
begin
      if isLast then
      begin
         len:=NewDimension;
         DynArraySetLength(PPointer(Value.GetRefereneToRawData)^,Value.TypeInfo,1,@len); //set length to NewDimension
         for i:=0 to NewDimension-1 do //Fill all with 0
           Value.SetArrayElement(i,NewValue2);
      end else
      begin
         len:=NewDimension;
         DynArraySetLength(PPointer(Value.GetRefereneToRawData)^,Value.TypeInfo,1,@len);//I will create len TValues
      end;
end;



var Index:array of integer;
    Value:TValue;
    ValuKind:TTypeKind;
......
......
....
Case token of
   tokInt:
   begin
        ValueKind:=tkInteger;
        Value:=0;   
   end;
 .....
 end;

 Index:=GetIndexFromSintacticTree;//for example if i have int[20][30] index=[20,30]
 for i:=0 to high(index) do
 begin
    if i = high(index) then CreateArray(Variable.Value,Index[i],ValueKind,Value,True)
    else CreateArray(Variable.Value,Index[i],ValueKind,Value,False)
    //Variable.Value is TValue
 end;
 //first TValue have 1 element, after that it will have 20 elements, and after that will have 20*30 elements


非常感谢,祝你今天愉快

要动态创建动态数组,需要对其类型信息结构的引用(
PTypeInfo
)才能传递到
DynArraySetLength
;调用
DynArraySetLength
并传递对nil指针的引用是创建新动态数组的方法。如果动态数组的特定形状在您的Delphi程序中不存在,编译器将不会为您生成特定的
PTypeInfo
指针。在这种情况下,您必须自己生成相应的
PTypeInfo
数据结构。这是可能的,尽管很乏味


坦率地说,我建议您使用与内置Delphi动态数组不同的结构来表示类似于脚本语言的问题中的数组。从长远来看,与尝试动态生成低级RTTI数据相比,这可能要少得多,因为RTTI单元中的抽象级别要高得多,因此,低级RTTI数据很可能会随着版本的变化而变化。

什么是TValue?RTTI与此有什么关系?你有哪个版本的Delphi?自Delphi 2010年以来,有一个新版本供反思,有了这个新的RTTI理论,你可以做任何事情。很难找到进入这个问题的动机,因为很难理解为什么有人会想这样做。除了你个人对Delphi泛型的厌恶之外,还有什么潜在的动机吗?我有一个软件,它有大约15000行代码,所有的代码都带有TValue和TValue数组(就像一种脚本语言)。现在很难改变。对于泛型,您无法动态分配新的泛型(而不是运行时),这是一个致命的问题。我有个问题要问你。你理解我的任务了吗?@David,@Golez:TValue是Delphi2010中添加的一种新类型。它是一个能够表示Delphi类型系统中任何值的记录。有点像变体,但不同。OP想要的是找到一种方法,使TValue包含在运行时定义的任意维度和基类型的动态数组。正如Barry指出的,这很困难,因为动态数组的工作方式。我真的希望TTypeInfo和TTypeData的格式不会改变,除非向TTypeData联合树添加新的分支,以填补现有RTTI中的空白。我在动态类和类型生成方面做了大量的理论工作,以实现通过RTTI与编译的Delphi代码无缝集成的脚本系统。我现在离有一到两个星期的POC编译器还差得远,当新版本出现时,必须完全返工我的类型数据生成代码,这将是相当烦人的。@Mason与其说是完全更改,不如说是在最后附加了更多的数据。在不破坏代码的情况下插入额外的数据真是一件好事。事实上,RTTI格式造成了相当大的尺寸损失,这主要是因为它的编码不能进行太多优化。最好考虑一些类似于.NET元数据表的东西,它使用一个简洁的表示。相反,Delphi RTTI留下的每个外部参照至少占用4个字节,并且经常为可以合并的名称提供冗余字符串。但在目前的框架内,这是不可能发生的。这很公平。试图编写代码来读取RTTI结构真是一团糟,因为所有的内联数据数组都没有静态大小,这意味着编译器无法找到下一个字段,您需要一堆指针数学。如果你的新格式可以摆脱这种情况,我会全力支持,我只需要重写一次生成代码。当你说“从一个版本到另一个版本”时,让我感到不安的是,这意味着每一个新版本都会(可能)进行格式修改,或者其中很大一部分。那将是一种痛苦。
Procedure CreateArray(var Value:TValue; NewDimmension:integer; NewValue2Kind:TTypeKind; NewValue2:TValue; IsLast:Boolean);
var i:integer;
NewValue:TValue;
len:Longint;
begin
   If Value.IsArray then// we have components in this dimension
   begin
       for i:=0 to Value.GetArrayLength-1 do// list all
       begin
            NewValue:=Value.GetArrayElement[i];
            CreateArray(newValue,NewDimension,NewValue2Kind,NewValue2,IsLast);
            Value.SetArrayElement(i,NewValue);
       end;
   end;
end else
begin
      if isLast then
      begin
         len:=NewDimension;
         DynArraySetLength(PPointer(Value.GetRefereneToRawData)^,Value.TypeInfo,1,@len); //set length to NewDimension
         for i:=0 to NewDimension-1 do //Fill all with 0
           Value.SetArrayElement(i,NewValue2);
      end else
      begin
         len:=NewDimension;
         DynArraySetLength(PPointer(Value.GetRefereneToRawData)^,Value.TypeInfo,1,@len);//I will create len TValues
      end;
end;



var Index:array of integer;
    Value:TValue;
    ValuKind:TTypeKind;
......
......
....
Case token of
   tokInt:
   begin
        ValueKind:=tkInteger;
        Value:=0;   
   end;
 .....
 end;

 Index:=GetIndexFromSintacticTree;//for example if i have int[20][30] index=[20,30]
 for i:=0 to high(index) do
 begin
    if i = high(index) then CreateArray(Variable.Value,Index[i],ValueKind,Value,True)
    else CreateArray(Variable.Value,Index[i],ValueKind,Value,False)
    //Variable.Value is TValue
 end;
 //first TValue have 1 element, after that it will have 20 elements, and after that will have 20*30 elements