Recent

Author Topic: varArryOf issue  (Read 6193 times)

Mando

  • Full Member
  • ***
  • Posts: 181
varArryOf issue
« on: October 28, 2016, 02:08:26 pm »
Hi all!!!!

Can anybody tell me what's wrong with this code?

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var arS: array of string;
  3.     arI: array of integer;
  4. begin
  5.  
  6.    try
  7.      arS:=varArrayOf(['Hola','Adios']);
  8.      showmessage('array of STRING creado correctamente');
  9.    except
  10.      showmessage('Error al crear array of STRING');
  11.    end;
  12.  
  13.    try
  14.      arI:=varArrayOf([1,2,3]);
  15.      showmessage('array of INTEGER creado correctamente');
  16.  
  17.    except
  18.      showmessage('Error al crear array of INTEGER');
  19.    end;
  20.  
  21. end;    
  22.  

I want to create and populate a open array of strings, but I get "Invalid variant type cast" error.
The array of integers creation works fine.

reagards.
« Last Edit: October 28, 2016, 07:03:06 pm by JuhaManninen »

Fungus

  • Sr. Member
  • ****
  • Posts: 353
Re: varArryOf issue
« Reply #1 on: October 28, 2016, 02:19:59 pm »
VarArrayOf returns an Variant array - not a dynamic "array of":

Code: Pascal  [Select][+][-]
  1. Var Strings: Array Of String;
  2. Begin
  3.   SetLength(Strings, 2);
  4.   Strings[0]:= 'First element';
  5.   Strings[1]:= 'Second element';
  6. End;

http://wiki.freepascal.org/Dynamic_array

Mando

  • Full Member
  • ***
  • Posts: 181
Re: varArryOf issue
« Reply #2 on: October 28, 2016, 06:55:27 pm »
Thanks for your answer, but I used the same code with delphi many year ago and it worked.




Regards

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: varArryOf issue
« Reply #3 on: October 28, 2016, 07:02:04 pm »
Thanks for your answer, but I used the same code with delphi many year ago and it worked.
Perhaps you have but, most certainly not on an array of string or array of integer.

If you want that functionality then change your arS and arI variables to type variant.

Fungus

  • Sr. Member
  • ****
  • Posts: 353
Re: varArryOf issue
« Reply #4 on: October 28, 2016, 07:32:08 pm »
It may be luck that it works with integers, but with strings you should consider the following code:

Code: Pascal  [Select][+][-]
  1. //Uses Variants;
  2. Type TStringArray = Array Of String;
  3.  
  4. Function MakeStringArray(Const TheArray: Array Of String): TStringArray;
  5. Var I, L: Integer;
  6. Begin
  7.   L:= High(TheArray) - Low(TheArray) + 1;
  8.   SetLength(Result, L);
  9.   For I:= 0 To L - 1 Do Result[I]:= TheArray[I];
  10. End;
  11.  
  12. Function MakeStringArrayFromVar(Const TheArray: Variant): TStringArray;
  13. Var I, L: Integer;
  14. Begin
  15.   If VarIsArray(TheArray) And (VarArrayDimCount(TheArray) = 1) Then Begin
  16.     L:= VarArrayHighBound(TheArray, 1) - VarArrayLowBound(TheArray, 1) + 1;
  17.     SetLength(Result, L);
  18.     For I:= 0 To L - 1 Do Result[I]:= VarAsType(TheArray[I], varString);
  19.   End Else SetLength(Result, 0); //Failure
  20. End;
  21.  
  22. Procedure TestIt;
  23. Var SA: TStringArray;
  24. begin
  25.   SA:= MakeStringArray(['abc', 'def', 'ghi']);
  26.   WriteLn(SA[0] + SA[1] + SA[2]);
  27.   //ShowMessage(SA[0] + SA[1] + SA[2]);
  28.   SA:= MakeStringArrayFromVar(VarArrayOf(['abc', 'def', 'ghi']));
  29.   WriteLn(SA[0] + SA[1] + SA[2]);
  30.   //ShowMessage(SA[0] + SA[1] + SA[2]);
  31. End;

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: varArryOf issue
« Reply #5 on: October 28, 2016, 08:18:54 pm »
ok apparently i was mistaken  :-[

Doing it manually delivers the similar error.
Code: [Select]
procedure Test2;
type
  TStringArrayType = array of string;
var
  i  : Integer;
  V  : Variant;
  sa : TStringArrayType;
begin
  V := varArrayOf(['Hola','Adios']);
  DynArrayFromVariant( Pointer(sa), V, TypeInfo( TStringArrayType ));

  for i := low(sa) to High(sa) do write('"',sa[i], '" ');
end;
It errors on the call to DynArrayFromVariant when using strings. Using shortstrings did not helped.

ASerge

  • Hero Member
  • *****
  • Posts: 2246
Re: varArryOf issue
« Reply #6 on: October 29, 2016, 02:44:19 am »
Doing it manually delivers the similar error.
...
It errors on the call to DynArrayFromVariant when using strings. Using shortstrings did not helped.
If you look in the code Variants, you can see that the string type is not supported by this procedure. But WideString - yes.
Strangely enough just add
Code: Pascal  [Select][+][-]
  1. varString: PString(dynarriter.data)^:=temp;
in the source code and the procedure will work. Why deleted the string type is a mystery.

Thaddy

  • Hero Member
  • *****
  • Posts: 14377
  • Sensorship about opinions does not belong here.
Re: varArryOf issue
« Reply #7 on: October 29, 2016, 10:33:12 am »
Why deleted the string type is a mystery.

No it is not. If it was available it is a bug-fix :) : widestring is not a refcounted string type,but a COM BSTR/BWSTR alias. A Pascal AnsiString or UnicodeString is reference counted. Hence the latter two do not fit the mechanism that is used for VarArray types or complex variant types because they need finalization.
Under COM the widestring memory is marshaled by the COM supersystem. Under linux etc, the widestring is simply a non-reference counted 16 bit string type.

In general, in pure Pascal, AnsiString and UnicodeString are way more efficient and portable. But at the cost that they can't be used without transformations, e.g. casting, when interfacing with other languages or formats. The compiler does that automatically for you when you use a hardcast, but it is not a pointer-cast (which you might think) but a transformation/copy. After the hardcast the two copies are not interchangable anymore. Be aware of that. Assign it back to a Pascal type when needed.
« Last Edit: October 29, 2016, 10:51:31 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

ASerge

  • Hero Member
  • *****
  • Posts: 2246
Re: varArryOf issue
« Reply #8 on: October 30, 2016, 04:17:03 pm »
...widestring is not a refcounted string type,but a COM BSTR/BWSTR alias. A Pascal AnsiString or UnicodeString is reference counted...
What is it? In the context of the question - not working string and shortstring. I point out the workaround - WideString. It's work! Further point out that simply forgot to add support for the string. This addition is also working! What does it have to do with portable, marshalling, ref count etc.? Here it does not affect the code. And yes, of course I know it all.

Thaddy

  • Hero Member
  • *****
  • Posts: 14377
  • Sensorship about opinions does not belong here.
Re: varArryOf issue
« Reply #9 on: October 30, 2016, 05:49:25 pm »
A Widestring or a PChar conversion is NOT a pointer conversion, but compiler magic. (wich means conversions and copy is built into the compiler at a really low level)
Nuff said,,, >:D
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

 

TinyPortal © 2005-2018