lookin030577 0 Posted August 31, 2022 Hi everybody! I am transferring my old Delphi 6 code into IDE Delphi 10.4 Community Edition. I encounter a compilation error while using these lines: type TDoubleArray = array of double; var Value: Variant; //this variable is assigned to a dynamic array somewhere in the code ... procedure DoSomething; var rv: TDoubleArray; begin rv:=@TVarData(Value).VArray.Data; // here I get the compilation error "Incompatible types Dynamic array and Pointer" but in Delphi 6 this line is compiled without warnings rv:=TDoubleArray(@TVarData(Value).VArray.Data); //here I have no warnings about the compilation end; My question is why the first line is not allowed for the compiler? Many thanks in advance! Share this post Link to post
Remy Lebeau 1393 Posted August 31, 2022 50 minutes ago, lookin030577 said: I am transferring my old Delphi 6 code into IDE Delphi 10.4 Community Edition. I encounter a compilation error while using these lines By default, an array inside a Variant is stored as (a pointer to) a COM SAFEARRAY: https://docs.microsoft.com/en-us/archive/msdn-magazine/2017/march/introducing-the-safearray-data-structure https://docs.microsoft.com/en-us/windows/win32/api/oaidl/ns-oaidl-safearray Which is completely different than a Delphi-style dynamic array. The two are not compatible with each other. The only way to store a Delphi-style dynamic array AS-A dynamic array in a Variant is to use a custom Variant type: https://docwiki.embarcadero.com/RADStudio/en/Defining_Custom_Variants That being said, Delphi 10.2 and later are more strict about NOT letting you assign a raw Pointer to a dynamic array, as you are trying to do: So, you would have to type-cast the raw Pointer in order to get the old Delphi 6 behavior, eg: type TDoubleArray = array of double; var Value: Variant; //this variable is assigned to a dynamic array somewhere in the code ... procedure DoSomething; var rv: TDoubleArray; begin rv := TDoubleArray(TVarData(Value).VArray.Data); // note, no @ used here. Why would you want to assign a PPointer to a dynamic array??? ... end; But, it never made sense to me why anyone would ever want to do this, since this makes the dynamic array point at something that is not a valid dynamic array, and can't be accessed as a dynamic array. The structure of a SAFEARRAY and a dynamic array are completely different. In any case, to safely access the raw data of a SAFEARRAY, you MUST use the SafeArrayAccessData() function, which Delphi's RTL has wrapped in the VarArrayLock() function, eg: var Value: Variant; //this variable is assigned to a dynamic array somewhere in the code ... procedure DoSomething; var rv: PDouble; begin rv := PDouble(VarArrayLock(Value)); try // use rv as needed... finally VarArrayUnlock(Value); end; end; 1 Share this post Link to post
lookin030577 0 Posted August 31, 2022 Remi, thank you a lot, I will work closely with your suggestions. However, the first line in my code (that is the line used in Delphi 6) was not only successfully compiled there but also returned a valid array (surely, I used the VarType(Value) flags to check if it is an array and what type of the array) if executed. I hardly understand the whole strusture of TVarData and I agree that it looks strange to use pointer reference (@) to a pointer in this line: @TVarData(Value).VArray.Data where VArray.Data is a pointer according to the documentation. But this worked quite well in Delphi 6 so my great wonder now why it does not work in the later version of IDE. Share this post Link to post
Remy Lebeau 1393 Posted August 31, 2022 (edited) 2 hours ago, lookin030577 said: However, the first line in my code (that is the line used in Delphi 6) was not only successfully compiled there but also returned a valid array (surely, I used the VarType(Value) flags to check if it is an array and what type of the array) if executed. I hardly understand the whole strusture of TVarData and I agree that it looks strange to use pointer reference (@) to a pointer I honestly can't see how it could ever work to assign a pointer-to-pointer-to-data to a dynamic-array. What is the original code trying to accomplish, exactly? If it just wants to access the elements of the Variant array, there is no need to assign the raw data pointer to a dynamic array at all. Quote But this worked quite well in Delphi 6 I seriously doubt that. I would have to see how the original code is populating the Variant, and how it is accessing the dynamic array that is assigned from the Variant's raw data. Quote so my great wonder now why it does not work in the later version of IDE. Because it is not supposed to work (and you should not have relied on it to begin with, even if it did compile. Just because something compiles doesn't make it right). Embarcadero intentionally changed the compiler in a later version to no longer allow assigning a raw untyped Pointer to a dynamic array. Edited August 31, 2022 by Remy Lebeau Share this post Link to post
lookin030577 0 Posted September 1, 2022 I apologize for my inattentive analysis of my Delphi 6 code - the line with this text: rv:=@TVarData(Value).VArray.Data is never executed in my code - instead I use another way to implement the conversion between Variant and 1D/2D array of a given type. So it seems you are totally right with the supposing that this line is out-of-sense and should not work properly. My apologizes again and many thanks for help! Share this post Link to post