• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1697
  • Last Modified:

Casting an untyped method parameter

I am working with some legacy Delphi (5) code whereby I have to process a reference to an untyped method parameter.

      function TPort.ReadFromBuffer(var prmBfr; prmMaxBytes: longint): longint;

I get an error on compilation "operator not applicable to this operand type" when trying to associate a value to prmBfr.

The call to ReadFromBuffer contains a dereferenced pointer as the parameter:
e.g.
      bytesToRead := myPort.ReadFromBuffer(fDataBfr^, bytesToRead);

Whereby fDataBfr is declared as:

      fDataBfr: ^TDataBuffer;

And type:
      TDataBuffer = array [1..65535] of char;

How am I supposed to cast for prmBfr?
0
brenlex
Asked:
brenlex
  • 5
  • 2
  • 2
1 Solution
 
TommySzalapskiCommented:
The only operator I see in your code are the pointer dereference operator ^ and the assignment operator :=
 "operator not applicable to this operand type" means that you tried to use an operator on some variable that you can't use it on.

Exactly what line is that error pointing to? What is the type of bytesToRead?
0
 
brenlexAuthor Commented:
Within the method TPort.ReadFromBuffer the compiler error points to any attempt to assign a value to prmBfr (prmBfr := ...) I've tried an assortment of attempts using  @, Addr, ^, xxx as TDataBuffer etc with no joy.  Always the same compiler error.

bytesToRead is just an integer.  Please regard as irrelevant in this context.  For purpose, just read as:

      procedure TPort.ReadFromBuffer(var prmBfr; prmMaxBytes: longint);
0
 
Emmanuel PASQUIERFreelance Project ManagerCommented:
You just have to cast it with the correct type.

example (without other parameters) :
procedure ReadFromBuffer(var prmBfr);
begin
 TDataBuffer(prmBfr)[2]:='B';
end;

procedure Test;
Var
 DataBuf:TDataBuffer;
begin
 FillChar(DataBuf,10,'a');
 DataBuf[10]:=#0; // Input = 'aaaaaaaaaa'
 ReadFromBuffer(DataBuf);
 ShowMessage(pChar(@DataBuf)); // Output = 'aBaaaaaaaa'
end;

Open in new window

0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
TommySzalapskiCommented:
In order to use the assignment operator := the compiler needs to know how to handle the data on the right hand side. So it needs to know what type it is converting to and the simple cast of the left side will work. But if prmBuffer is untyped, I assume you want to be able to use it for more than just TDataBuffers otherwise why not just use TDataBuffer instead of var?

0
 
Emmanuel PASQUIERFreelance Project ManagerCommented:
procedures that have untyped var parameters are often just convenient generic functions, such as Move or FillChar, that are given an indication of the real type or the memory size of the parameter on another parameter. They are more versatile than typed parameters, and the compiler won't go crazy if you call the above ReadFromBuffer function with a string for example :

Var s:String;
begin
 s:='aaaaaaaaaa';
 ReadFromBuffer(s[1]); // Output s = 'aBaaaaaaaa'
end;

Open in new window


Those 'untyped var parameters' (UVP) are to be considered as generic pointers, that you have to cast. The difference with pointers parameters is that when you cast UVP you use directly the dereferenced type. It is totally equivalent, but with less fuss than this :
procedure ReadFromBuffer(prmBfr:Pointer);
begin
 pDataBuffer(prmBfr) ^ [2]:='B';
 // here you have to dereference, and also you need the declaration of the pointer type pDataBuffer,
 // where in the previous case I don't really need declaring pDataBuffer, as TDataBuffer is enough
end;

procedure Test;
Var
 DataBuf:TDataBuffer;
begin
 FillChar(DataBuf,10,'a');
 DataBuf[10]:=#0;
 ReadFromBuffer(@DataBuf); // here you have to get the pointer
 ShowMessage(pChar(@DataBuf));
end;

Open in new window


Another funny kind of parameters are Variant open array parameters, like the one used in Format function :
function Format(const Format: string; const Args: array of const): string;

these kind of parameters are also extremely useful to make generic functions, AND these provide the type of each parameter, that can be used inside the function
 for I := 0 to High(Args) do
    with Args[I] do
      case VType of
        vtInteger: ...

Open in new window

have a look in Delphi help for Variant open array parameters if you want to know more
0
 
brenlexAuthor Commented:
Thanks for the responses but it differs slightly from my initial question.

The call to ReadFromBuffer involves the passing of a dereferenced pointer as the untyped parameter:
      myPort.ReadFromBuffer(fDataBfr^, bytesToRead);
where fDataBfr : ^TDataBfr;

I am unable to change this call -- it must remain the same in existing code. I therefore am unable to apply your code logic in the examples to pass in ReadFromBuffer(@DataBuf) or casting ReadFromBuffer(DataBuf) where Databuf:TDataBuffer, and hence cast to TDataBuffer from within the method.

I am struggling with my syntax within the ReadFromBuffer method to assign a value to which fDataBfr points to.
0
 
Emmanuel PASQUIERFreelance Project ManagerCommented:
I don't see in what way what you want differs from what you need.
procedure ReadFromBuffer(var prmBfr);
begin
 FillChar(TDataBuffer(prmBfr),10,'a');
 TDataBuffer(prmBfr)[2]:='B';
 TDataBuffer(prmBfr)[10]:=#0;
end;

procedure Test;
Var
 DataBuf:pDataBuffer;
begin
 New(DataBuf);
 ReadFromBuffer(DataBuf^); // you can use dereferenced pointer 
 ShowMessage(pChar(DataBuf)); // Output = 'aBaaaaaaaa'
 Dispose(DataBuf);
end;

Open in new window

0
 
Emmanuel PASQUIERFreelance Project ManagerCommented:
I meant "in what way what you want differs from what I gave you "
0
 
Emmanuel PASQUIERFreelance Project ManagerCommented:
you should have select the post #36713073 as answer, don't forget that when others will be looking for answers in the knowledge DB, they will see the selected answer first. And the one you selected is not going to help them much
I'll call a moderator, if he can fix that
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.

Join & Write a Comment

Featured Post

Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

  • 5
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now