How to dynamically create and pass an array of const?

This is a tough one for VCL and inline assembly gurus.

I need to dynamically create the Value parameter to pass to the Format function.  (Or rewrite Format's existing functionality - ugh)

Review of common knowledge:

Format has the following declaration:
  Function Format (const aFormat: String; const values: array of const);


Problem:

The desired functionality is along the lines of:

function TMyRule.ResultString (fmt: String): String;
begin
    Params := BuildParams;
    aString := Format (fmt, Params);
end;

I have determined that the array of const is implemented as an array of TVarRec's.  I am uncertain about whether it is actually a variant array or not.  Either way, I can build it.  Any input?

BUT ... there is no syntactic model to pass the created array to the function.  The Pascal syntax only allows the array to be compiled in.

A review of the format function in SysUtils.pas suggests that it should be possible to write the call with an inline assembly call.  This is the real meat of the problem.  
dejohn99Asked:
Who is Participating?
 
MadshiCommented:
:-)

BTW, in the meanwhile you can accept a comment as the answer (new EE feature)...

Regards, Madshi.
0
 
MadshiCommented:
Well, at least in D5 you can do this:

type TVarRecArr = array of TVarRec;

function BuildParams : TVarRecArr;
begin
  SetLength(result, 5);
  // here fill the array
end;

begin
  Format('test', BuildParams);
end;

I think that should work for D4, too. For D2/3 you can perhaps do the same, but with this type declaration instead:

type TVarRecArr  = array [0..$FFFF] of TVarRec;
     TPVarRecArr = ^TVarRecArr;

function BuildParams : TPVarRecArr;
begin
  result := AllocMem(sizeOf(TVarRecArr) * 5);
  // here fill the array
end;

var params : TPVarRecArr;
begin
  params := BuildParams;
  try
    Format('test', params^);
  finally FreeMem(params) end;
end;

Look also at "Slice".

Does this help?

Regards, Madshi.
0
 
dejohn99Author Commented:
Thanks.

I'll try this an let you know what happens.

I'm using D3.02 C/S.
0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

 
sburckCommented:
Format's second parameter is what's called a variant open array .  This example, taken from the Delphi 4 help file, shows how to access it and build it up dynamically:
---From the Help ----
Variant open array parameters allow you to pass an array of differently-typed expressions to a single procedure or function. To define a routine with a variant open array parameter, specify array of const as the parameter’s type. Thus

procedure DoSomething(A: array of const);

declares a procedure called DoSomething that can operate on heterogeneous arrays.
The array of const construction is equivalent to array of TVarRec. TVarRec, declared in the System unit, represents a record with a variant part that can hold values of integer, Boolean, character, real, string, pointer, class, class reference, interface, and variant types. TVarRec’s VType field indicates the type of each element in the array. Some types are passed as pointers rather than values; in particular, long strings are passed as Pointer and must be typecast to string.

The following example uses a variant open array parameter in a function that creates a string representation of each element passed to it and concatenates the results into a single string. The string-handling routines called in this function are defined in SysUtils.

function MakeStr(const Args: array of const): string;

const
  BoolChars: array[Boolean] of Char = ('F', 'T');
var
  I: Integer;
begin
  Result := '';
  for I := 0 to High(Args) do
    with Args[I] do
      case VType of
        vtInteger:    Result := Result + IntToStr(VInteger);
        vtBoolean:    Result := Result + BoolChars[VBoolean];
        vtChar:       Result := Result + VChar;
        vtExtended:   Result := Result + FloatToStr(VExtended^);

        vtString:     Result := Result + VString^;
        vtPChar:      Result := Result + VPChar;
        vtObject:     Result := Result + VObject.ClassName;
        vtClass:      Result := Result + VClass.ClassName;
        vtAnsiString: Result := Result + string(VAnsiString);
        vtCurrency:   Result := Result + CurrToStr(VCurrency^);
        vtVariant:    Result := Result + string(VVariant^);
        vtInt64:      Result := Result + IntToStr(VInt64^);

    end;
end;

We can call this function using an open array constructor (see Open array constructors). For example,

MakeStr(['test', 100, ' ', True, 3.14159, TForm])

returns the string “test100 T3.14159TForm”.

--- End of the help file insert----

This is what you are looking for, I believe.

0
 
dejohn99Author Commented:
Madshi:  Your solution worked perfectly.  Please submit as an answer for your points.  Thanks a million!

SBurck: Thanks for the info.  I must have been in a pre-christmas brain death when I read this the first time(it's exactly the same in the D3 help).  This is where I got the info I needed to build the structure in the first place.  Sigh.
0
 
dejohn99Author Commented:
Thanks
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.