Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Generic Pointer Application

Status
Not open for further replies.

Glenn9999

Programmer
Jun 19, 2004
2,311
0
36
US
I thought I'd put a small exercise I'm trying to work out fully on here.

Say you are creating a procedure to get input from a hardware device of some kind. Basically to be compatible with Pascal's strong typing, we would have to pass the spot we want the data in as a pointer address so multiple types of data (for Pascal's perspective) can come in.

So we end up with a prototype like:

procedure GetDataFromDevice(var indata: pointer; datasize: longint);

where indata is the pointer, and datasize is the length in bytes of the data to return.

So, you would call it in a main program something like:

GetDataFromDevice(@myvar, sizeof(myvar));


How would you proceed with getting something like this written, instead of having to write a proc for every type and size of data you intend to return?
 
You treat it just like "blockread", but deriving the data from your device rather than a file.

i.e. you have one procedure, reading from one device. The parameters sent to this procedure tell it (a) how many bytes/words/records/whatever to read, and (b) where to put them. I wouldn't get too worried about genericness. The getdatafromdevice procedure must know a little about the device, so it knows whether the data will naturally arrive in words, bytes, or some other size. The calling procedure is also certain to know at least a little about the data (though it needn't know anything about the hardware operation of the device).

The getdatafrom... procedure is basically going to be a loop (datasize) long, retrieving a byte from the device, saving it at the specified location, and advancing its location pointer by one. Or something similar.
 
Ok the specific problem I have is that I'm trying to get this done via blockread() for now, but I can replace this with my direct hardware access routines, which would be similar in scope.

The problem comes in the fact that I find I need to typecast the pointer sent in order to do something with it (the Pascal strong-typed language thing). The blockread call isn't honoring its parms, but returning data based on the typecast I happen to give the pointer, which makes that 2nd parm of length irrelevant (that I do not want). If I were to do "blockread(infile, mydata^, mydata_length, amount_read)" with mydata_length less than whatever I typecast the pointer to, amount_read always returns 0, and I overwrite parts of memory I'm not supposed to overwrite.

Even if I pull data in byte by byte, I would have to have a way to stick that on the exact address I'm given.

So basically if I were to substitute blockread I would have to read into a temp area, move() the bytes I need to the pointer address, then seek the file backwards (blocksize - datalength) bytes.

Is there a better way to approach something like this?
 
I'm not sure I understand.

You should be able to do:
blockread(mypointer^, datalength);
with myrecord(mypointer^) do whatever you want.

The only problem is that this will only look at the first record you've brought in, and further records will be accessed by moving a pointer further on by the length of myrecord.

You certainly shouldn't need to move the actual data from place to place; blockread will read in as many bytes as you want (up to a segment in 16-bit), wherever you want.
 
Okay, sorry, I had some more pressing matters to attend to:

What I'm trying to do is get a function that will return the number of bytes I give it back to me. So if I ask for 22 bytes it'll return the next 22 bytes. If I ask for 300 bytes it'll return 300 bytes. And so on and so on.

The problem is I don't want to exactly kick in a loop where I read one byte at a time (that would solve the problem) or set up some caching scheme, but the other problem is I have to set a specific type-cast to be able to get the read to work.

What I'm observing is the blockread is taking the length of the typecast and not the length I'm providing it. So when the data from the blockread gets copied to the pointer, it overwrites the memory after the data in question.

Hope this helps. Basically I'm asking if there's any way to defeat the strong type-casting and use a universal parm.
 
I don't think you need to worry about typecasting. If you use reset(myfile,1) and blockread with a simple, untyped generic pointer, blockread will read the number of bytes asked. (You could write alternative procedures reading random data from other places, and make them behave the same way, if desired)

Later, when you want to do something with the data, you can typecast your pointer there.

var
Space : pointer;
MyPtr : pointer;

blockread(myfile, Space^, NoBytes);
...
...
MyPtr := Space;
with MyType(MyPtr^) do
begin
do whatever you feel like.
end;

You can, of course, typecast "Space", but very often you will have read in several records into this space, so you will want to be able to move the pointer you're using for referencing records.

Because I'm not a particularly good programmer, I tend to use one of two methods to access a whole set of MyRecords read into Space:

(1)
while not at end of Space do
begin
do things
inc(word(MyPtr), sizeof(MyType));
end;
{ note that I increment word(myptr), not word(myptr^); the idea is to change the pointer, not the data }

(2)
type
MyType = record
definition...
end;
MyTypeArray = array[0..lots] of MyType;

Note that MyTypeArray doesn't occupy any memory, no matter how large "lots" is. It's simply a template.

with MyTypeArray(Space^)[subscript] do
begin
end;

 
Okay, I think I got what I needed. Thank you.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top