Solved

Casting an untyped method parameter

Posted on 2011-09-27
10
1,448 Views
Last Modified: 2012-05-12
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
Comment
Question by:brenlex
  • 5
  • 2
  • 2
10 Comments
 
LVL 37

Expert Comment

by:TommySzalapski
ID: 36710646
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
 

Author Comment

by:brenlex
ID: 36710974
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
 
LVL 25

Expert Comment

by:epasquier
ID: 36711491
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
 
LVL 37

Expert Comment

by:TommySzalapski
ID: 36711718
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
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 25

Expert Comment

by:epasquier
ID: 36713073
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
 

Author Comment

by:brenlex
ID: 36715937
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
 
LVL 25

Accepted Solution

by:
epasquier earned 500 total points
ID: 36716005
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
 
LVL 25

Expert Comment

by:epasquier
ID: 36716009
I meant "in what way what you want differs from what I gave you "
0
 
LVL 25

Expert Comment

by:epasquier
ID: 36716394
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

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now