Solved

Casting an untyped method parameter

Posted on 2011-09-27
10
1,501 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
Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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
 
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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Delphi IDE crash without error message ... 7 99
Convert GUI app into console app for Win32 Env 5 112
Delphi Yen format 3 45
Delphi...Split view - idea? 1 90
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
The CRUD Functions CRUD, meaning "Create, Read, Update, Delete (http://en.wikipedia.org/wiki/Create,_read,_update_and_delete)" is a common term to data base developers.  It describes the essential functions of data base table maintenance.  This art…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

807 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