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