Recent

Author Topic: Conditional variable definition?  (Read 2741 times)

CM630

  • Hero Member
  • *****
  • Posts: 1251
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Conditional variable definition?
« on: January 24, 2025, 08:57:05 am »
Is it possible to define a variable in code, according to some condition?
Something like this:



Code: Pascal  [Select][+][-]
  1. procedure MyProc(aInteger: Integer; Bitness: byte);
  2. var
  3.   {$if (Bitness = 16)}
  4.     myData: array of Word;
  5.   {$else}
  6.     myData: array of DWord;
  7.   {$endif}
  8. begin
  9.  
  10.  
  11. end;  

I think the answer is “No”, but I prefer to be sure.
If not possible, what are the other possible solutions?
The one that I think of is


Code: Pascal  [Select][+][-]
  1. procedure MyProc(aInteger: Integer; Bitness: byte);
  2. var
  3.    myData16: array of word;
  4.   myData32: array of Dword;
  5.  
  6.  
  7. begin
  8.   if Bitness = 16
  9.     then SetLength(myData16,xxx)
  10.     else SetLength(myData32,xxx);
  11.   //Select which var to use in each case necessary
  12. end;  

Or could I use a variant?
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

TRon

  • Hero Member
  • *****
  • Posts: 3982
Re: Conditional variable definition?
« Reply #1 on: January 24, 2025, 09:07:14 am »
yes, is possible. In the particular case of your example there are (compiler) defines that are active during compilation.

You can ofc also provide a define yourself. The use of assigning a value to a macro is uncommon but possible by setting the directive macro on (https://www.freepascal.org/docs-html/prog/progsu48.html#x55-540001.2.48).

edit: you can also check for constant values by using if, see conditionals
« Last Edit: January 24, 2025, 09:11:29 am by TRon »
I do not have to remember anything anymore thanks to total-recall.

440bx

  • Hero Member
  • *****
  • Posts: 5004
Re: Conditional variable definition?
« Reply #2 on: January 24, 2025, 09:11:19 am »
I normally test for WIN32 or WIN64 to determine the bitness (I only deal with Windows, so that's sufficient.)

if you want a test that is not Windows specific, I _believe_ (that means, I haven't used what follows) you can use CPU16, CPU32 and CPU64 to determine the bitness.

Your code would look something like this (presuming it's running under Windows):
Code: Pascal  [Select][+][-]
  1. {$ifdef WIN16}
  2.   myData : array of word;
  3. {$else}
  4.   myData : array of DWORD;  { for 32 and 64 bit }
  5. {$endif}
  6.  
  7. { etc }
  8.  
  9.  

If you're not using Windows then you should probably use the CPUxx to determine which bitness applies.

HTH.


(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

d2010

  • Jr. Member
  • **
  • Posts: 94
Re: Conditional variable definition?
« Reply #3 on: January 24, 2025, 09:14:27 am »
Code: [Select]
var xxx:integer=32767;
procedure MyProc(aInteger: Integer; Bitness: byte);
var
  myData32: array of Dword;
 J:integer;
begin
   SetLength(myData32,xxx);
   if Bitness = 08 then
   for J:=01 to length(myData32) do myData32[J]:=aInteger and 255 else
   if Bitness = 16 then
   for J:=01 to length(myData32) do myData32[J]:=aInteger and 65535 else
   for J:=01 to length(myData32) do myData32[J]:=aInteger;
End;
Var arsenieBoca:string='Cârma minții - Părintele Arsenie Boca';
 

CM630

  • Hero Member
  • *****
  • Posts: 1251
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Conditional variable definition?
« Reply #4 on: January 24, 2025, 10:14:42 am »
It seems that I was not clear enough, at least the posts of @d2010 and @440bx make me think like this.
Bitness is not the bitness of the OS, actually, in my particular case it is the bitness of data, which I get from a DLL.
In some cases, the DLL needs to store the value in an array of Word, in others it needs to store it in an array of Dword.

So what I need is to define the variable according to a parameter of the routine, in my example, it is Bitness: byte.

I will check further the links in @TRon's post,
Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

TRon

  • Hero Member
  • *****
  • Posts: 3982
Re: Conditional variable definition?
« Reply #5 on: January 24, 2025, 10:22:42 am »
In that case my post would be in the wrong category as well.

If at runtime you require to account for bitness then compiler defines are not very helpful as they are only meant to be used at compile time.

The quickest I am able to come up with is an array (whatever which type) and assign the first item to a pointer pointing to either a word or a dword depending on the bitness, e.g.
Code: Pascal  [Select][+][-]
  1. type
  2.   P16 : ^word;
  3.   P32 : ^dword;
  4.  
  5. var
  6.   Data : array of byte;
  7.  
  8. ...
  9.   if bitness = 16 then setlength(data, n * 2) else
  10.   if bitness = 32 then setlength(data, n * 4);
  11.  
  12.   P16 := @data[0];
  13.   P32 := @data[0];
  14.  
  15.   p32[0] := valuedword;
  16.   p16[0] := valueword;
  17.  

Dunno if it could be implemented in a more elegant manner and/or more agnostic.
« Last Edit: January 24, 2025, 10:34:39 am by TRon »
I do not have to remember anything anymore thanks to total-recall.

440bx

  • Hero Member
  • *****
  • Posts: 5004
Re: Conditional variable definition?
« Reply #6 on: January 24, 2025, 11:07:58 am »
in my particular case it is the bitness of data, which I get from a DLL.
In some cases, the DLL needs to store the value in an array of Word, in others it needs to store it in an array of Dword.

So what I need is to define the variable according to a parameter of the routine, in my example, it is Bitness: byte.
As a result of the information you provided above, I have a question: does the DLL inform you of the number of elements the array must be able to accommodate at the same time (or roughly the same time) as it informs you of the array elements type or do you need to be able to dynamically resize the array at runtime ? (IOW, the DLL knows if it needs an array of words or dwords and knows how many of them upfront or it knows only the type upfront and not the array size/(element count))
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

CM630

  • Hero Member
  • *****
  • Posts: 1251
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: Conditional variable definition?
« Reply #7 on: January 24, 2025, 11:34:10 am »

I think this sample without a DLL should represent the case:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3.  
  4. {$mode objfpc}{$H+}
  5.  
  6.  
  7. interface
  8.  
  9.  
  10. uses
  11.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs;
  12.  
  13.  
  14. type
  15.  
  16.  
  17.   Word1D = array of word;
  18.   DWord1D = array of Dword;
  19.  
  20.  
  21.   { TForm1 }
  22.  
  23.  
  24.   TForm1 = class(TForm)
  25.     procedure FormCreate(Sender: TObject);
  26.   private
  27.  
  28.  
  29.   public
  30.  
  31.  
  32.   end;
  33.  
  34.  
  35. var
  36.   Form1: TForm1;
  37.  
  38.  
  39. implementation
  40.  
  41.  
  42. {$R *.lfm}
  43.  
  44.  
  45. { TForm1 }
  46.  
  47.  
  48. procedure Mf16(var InData: array of word);
  49. var
  50.   i: integer;
  51. begin
  52.   for i:= 0 to high(InData) do
  53.     InData[i]:= i;
  54. end;
  55.  
  56.  
  57. procedure Mf32(var InData: array of Dword);
  58. var
  59.   i: integer;
  60. begin
  61.   for i:= 0 to high(InData) do
  62.     InData[i]:= i;
  63. end;
  64.  
  65.  
  66. procedure TForm1.FormCreate(Sender: TObject);
  67. var
  68.   MyDataW: array of word;
  69.   MyDataDW: array of Dword;
  70. begin
  71.   SetLength(MyDataW,10);
  72.   SetLength(MyDataDW,10);
  73.   Mf16(MyDataW);
  74.   mf16(Word1D(MyDataDW));//This line compiles and executes, but returns a wrong result
  75.   Mf32(MyDataDW);
  76. end;
  77.  
  78.  
  79. end.
  80.  

Sometimes I need to call and process the data from procedure Mf16, and sometimes I need to use procedure Mf32.
I get info from the DLL which procedure shall be used.
So the question is it possible to use only one variable and define according to my needs. I think in C I can define a variable wherever I want (there is no dedicated var section there).
So I am trying to find if the same is doable in FPC:
  if a = true then MyData : array of Word else MyData : array of DWord;

Лазар 4,0RC2 32 bit (sometimes 64 bit); FPC3,2,2

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12042
  • FPC developer.
Re: Conditional variable definition?
« Reply #8 on: January 24, 2025, 12:31:31 pm »
Sometimes I need to call and process the data from procedure Mf16, and sometimes I need to use procedure Mf32.

I have had the same issue with an own graphics (bitmap) class. It could be 8,16 and 32-bit.  I solved it with a generic, and a case statement for places where it matters. Many such places can be eliminated away using virtual methods in some non generic base class that are overriden by the generic.


Quote
I get info from the DLL which procedure shall be used.
So the question is it possible to use only one variable and define according to my needs. I think in C I can define a variable wherever I want (there is no dedicated var section there).

C has the same issues. You can do such things, but only if a is a preprocessor symbol. In Pascal, (true) constants are not preprocessor symbols, so they are also allowed.

But if the symbol to check is runtime, that won't work here in either language.

Zvoni

  • Hero Member
  • *****
  • Posts: 2844
Re: Conditional variable definition?
« Reply #9 on: January 24, 2025, 12:55:32 pm »
Then, i think, Tron has it right, since in C arrays are basically pointers.
If your DLL tells you which Function to use (and therefore which size of the Array-Elements it expects), then you should know which array to use.
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

TRon

  • Hero Member
  • *****
  • Posts: 3982
Re: Conditional variable definition?
« Reply #10 on: January 24, 2025, 01:39:38 pm »
I thought I abstract it away behind an advanced record but got stuck on the indexed property writing at the wrong location, e.g. it seems that
Code: Pascal  [Select][+][-]
  1. type
  2.   TData =
  3.   record
  4.     Data    : packed array of byte;
  5.     bitness : integer;
  6.    private
  7.     function  GetItem(Index: integer): int64;
  8.     procedure SetItem(index : integer; value: int64);
  9.    public
  10.     property  Items[index: integer]: int64 read getItem write SetItem; default;
  11.   end;
  12.  
  13.  
  14. procedure TData.SetItem(index: integer; value: int64);
  15. // final solution when working is much smarter than this. Only here to illustrate the issue
  16. var
  17.   P16 : PWord;
  18.   P32 : PDWord;
  19. begin
  20.   case Self.bitness of
  21.     16 : begin P16 := @Self.Data[0]; P16[index] :=  word(value); end;
  22.     32 : begin P32 := @Self.Data[0]; P32[index] := dword(value); end;
  23.   end;
  24. end;
  25.  
  26.  
  27. var
  28.   MyData : TData;
  29.  
  30. ..
  31.  
  32. MyData[0] := 10;
  33.  
.. writes that value 10 before the Data variable field in memory (heaptrace tells). Is that a known issue/behaviour or am I daft today ? FPC 3.2.2 (not able to test trunk or fixes atm)

(and yes, the size of the array was set before assigning a value and everything seems aligned properly)
I do not have to remember anything anymore thanks to total-recall.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12042
  • FPC developer.
Re: Conditional variable definition?
« Reply #11 on: January 24, 2025, 01:41:46 pm »
@TRon, you don't setlength() the dynamic array

TRon

  • Hero Member
  • *****
  • Posts: 3982
Re: Conditional variable definition?
« Reply #12 on: January 24, 2025, 01:45:22 pm »
@TRon, you don't setlength() the dynamic array
see remark at the end of my message  ;D.

But you are right it is a bit difficult to look at when you do not have the full code.

Code: Pascal  [Select][+][-]
  1. type
  2.   TData =
  3.   record
  4.     Data    : packed array of byte;
  5.     bitness : integer;
  6.    private
  7.     function  GetItem(Index: integer): int64;
  8.     procedure SetItem(index : integer; value: int64);
  9.     procedure Dump;
  10.     procedure SetLength(Len: SizeInt);
  11.    public
  12.     property  Items[index: integer]: int64 read getItem write SetItem; default;
  13.   end;
  14.  
  15.  
  16. procedure TData.SetLength(Len: SizeInt);
  17. begin
  18.   system.SetLength(Self.Data, Len * (Self.Bitness shr 3));
  19.   writeln('address of data = $', HexStr(@Self.Data[0]));
  20. end;
  21.  
  22.  
  23. procedure TData.Dump;
  24. var
  25.   i: integer;
  26. begin
  27.   writeln('bitness = ', Self.Bitness);
  28.   for i := low(Self.Data) to high(Self.Data)
  29.     do writeln(Self.Data[i]:3);
  30. end;
  31.  
  32. function  TData.GetItem(Index: integer): int64;
  33. var
  34.   P16 : PWord;
  35.   P32 : PDWord;
  36. begin
  37.   case Self.Bitness of
  38.     16 : begin P16 := @Self.Data[0]; result := P16[Index]; end;
  39.     32 : begin P32 := @Self.Data[0]; result := P32[Index]; end;
  40.   end;
  41. end;
  42.  
  43.  
  44. procedure TData.SetItem(index: integer; value: int64);
  45. var
  46.   P16 : PWord;
  47.   P32 : PDWord;
  48. begin
  49.   case Self.bitness of
  50.     16 : begin P16 := @Self.Data[0]; P16[index] :=  word(value); end;
  51.     32 : begin P32 := @Self.Data[0]; P32[index] := dword(value); end;
  52.   end;
  53. end;
  54.  
  55.  
  56. procedure Mfagnostic(var inData: TData);
  57. var
  58.   i: integer;
  59. begin
  60.   for i:= 0 to high(InData.Data)
  61.     // THIS BUGS
  62.     do InData[i]:= i;
  63. end;
  64.  
  65. var
  66.   MyData : TData;
  67. begin
  68.   MyData := default(TData);
  69.   MyData.Bitness := 16;
  70.   MyData.SetLength(10);
  71.   mfagnostic(MyData);
  72. end.
  73.  
I do not have to remember anything anymore thanks to total-recall.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12042
  • FPC developer.
Re: Conditional variable definition?
« Reply #13 on: January 24, 2025, 02:01:14 pm »
Right, new attempt: Mfagnostic loops over bytes, but P16[] and p32[] in setitem access as many 16 and 32-bit elements as there are bytes, i.e. the loop iterates 2 resp 4 times too much

Zvoni

  • Hero Member
  • *****
  • Posts: 2844
Re: Conditional variable definition?
« Reply #14 on: January 24, 2025, 02:36:44 pm »
Right, new attempt: Mfagnostic loops over bytes, but P16[] and p32[] in setitem access as many 16 and 32-bit elements as there are bytes, i.e. the loop iterates 2 resp 4 times too much
Correct.
What's missing is the "Step"-Size for the Iterator.
For P16 it should be 2, for P32 should be 4
Since we don't have a "Step" in For-Loop, maybe a repeat-Until with Inc(i,2) (For P16) resp. Inc(i,4) (for P32)?
And not a "normal" assignment, but maybe a System.Move?
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

 

TinyPortal © 2005-2018