The declaration of WriteFile, ReadFile win32 api may be incorrect.It is incorrect but, you won't get it fixed. The incorrect definition has been in use for years and correcting it would likely break a fair amount of code, it's not going to happen.
What I do grant you however is that we don't have the equivalent declaration as an overload. Those should in my opinion definitely be there as those declarations with untyped parameters or typed var parameters are considered "convenience" declarations and thus an "add on".
Windows.WriteFile(my_hdl, buf, buf_len, written_bytes, nil) Windows.ReadFile(my_hdl, buf, buf_len, read_bytes, nil);
Invalid Buffer value is passed in win64 build mode.
The access viloation exception occurs in win32 build mode when ReadFile is called.
and it works for more than twenty years without any problem.and, it could work for 20,000 years and it would still be wrong because it should NOT be necessary to dereference the Buffer variable.
OP started this thread because he got errors, and supposed that these errors were due to incorrect declarations. I simply gave him example of code (from heavily used library) using these declarations without errors.and it works for more than twenty years without any problem.and, it could work for 20,000 years and it would still be wrong because it should NOT be necessary to dereference the Buffer variable.
Also, since the variable Buffer is just a "pointer", what is Buffer^ supposed to be pointing to ?... a byte ?.. a word ?... a qword ?... mother Theresa ?... the neighbor's dog ? ... semantically, dereferencing a generic pointer is meaningless since it doesn't point to a known type.
and it works for more than twenty years without any problem.and, it could work for 20,000 years and it would still be wrong because it should NOT be necessary to dereference the Buffer variable.
Also, since the variable Buffer is just a "pointer", what is Buffer^ supposed to be pointing to ?... a byte ?..
a word ?... a qword ?... mother Theresa ?... the neighbor's dog ? ... semantically, dereferencing a generic pointer is meaningless since it doesn't point to a known type.
a word ?... a qword ?... mother Theresa ?... the neighbor's dog ? ... semantically, dereferencing a generic pointer is meaningless since it doesn't point to a known type.
yes, an overload (using the correct definition) would definitely be a good thing in this case and, it seems its presence would not break any existing code.
Windows.WriteFile(my_hdl, buf, buf_len, written_bytes, nil) Windows.ReadFile(my_hdl, buf, buf_len, read_bytes, nil);
Invalid Buffer value is passed in win64 build mode.
The access viloation exception occurs in win32 build mode when ReadFile is called.
You didn't write what were your parameters, and how you passed them exactly.
This is how it is done e.g. in synaser.pas:
var FHandle: THandle; Buffer: pointer; Length: longint; Result: longint; Overlapped: TOverlapped; ... WriteFile(FHandle, Buffer^, Length, DWord(Result), @Overlapped); ReadFile(FHandle, Buffer^, Length, Dword(Result), @Overlapped);
and it works for more than twenty years without any problem.
But I don't understand the difference between 'buf' and 'buf^'.in the call to Windows.WriteFile, buf^ dereferences buf but since the parameter is untyped what ends up being passed is buf, i.e, @buf^ = buf, which is what should have been passed without all these binary contortions.
Note that WriteFileEX does have an overload.WriteFileEx is defined correctly, that is, the buffer parameter is of type pointer as it should be. That's one more reason there should be an overload for WriteFile with "Buffer : pointer" because those two functions are supposed to differ _only_ in the fact that WriteFileEx takes an additional parameter but, all the other parameters they have in common should be identical and, currently, they aren't.
I would not be so sure:Note that WriteFileEX does have an overload.WriteFileEx is defined correctly, that is, the buffer parameter is of type pointer as it should be.
[in, out] LPOVERLAPPED lpOverlapped,But I have found only one WriteFileEx (in redef.inc), where is overload?
But I have found only one WriteFileEx (in redef.inc), where is overload?
Thank you for information.But I have found only one WriteFileEx (in redef.inc), where is overload?
in func.inc
function WriteFileEx(hFile:HANDLE; lpBuffer:LPCVOID; nNumberOfBytesToWrite:DWORD; lpOverlapped:LPOVERLAPPED; lpCompletio nRoutine:LPOVERLAPPED_COMPLETION_ROUTINE):WINBOOL; external 'kernel32' name 'WriteFileEx';
But by default the declaration from redef.inc is used, so this overload is still not very helpful for C-minded beginners.:D That is hilarious. The incorrect definition of WriteFile is more of a problem to an experienced programmer than a beginner. An experienced C programmer expects the definition to be as MS defined it (if you wonder why that is, it's got something to do with the fact that MS authored the O/S the function is used in but, that's a small, 25 million line of code detail.)
:D That is hilarious.That's what it's designed for ;)
The incorrect definition of WriteFile..You may call it incorrect, others call it correct, I don't care, as it works as expected. 8-)
An experienced C programmer expects the definition to be as MS defined it?? My experience in C was much longer, than in Pascal, but I didn't expect that Pascal declaration would be exactly as C. And what does unexperienced programmer expect?
Since Pascal can replicate _exactly_ the C definition, there is no justifiable reason to have one that is semantically different that does _not_ function like the original.On the other hand, there is no justifiable reason _not_ to have one. This is
In the case of FPC, the justification is that Delphi defined it that way and for compatibility FPC followed but, it doesn't make it right.Compatibility, in the first place with existing code, is the sacred cow. We still write such things like LPVOID and wait for long pointers to return... ::)
And, to make matters worse, the definitions of WriteFile and WriteFileEx are not parallel (they should be.)I would like to have your problems... :D
On the other hand, there is no justifiable reason _not_ to have one. This isbut there _is_ a good reason not to have one and, that is, when a programmer searches for the documentation on an API function, what shows up is MS' documentation and, calling Pascal's WriteFile as it is documented in MSDN will _not_ work and, there is _no_ Free Pascal page that documents the fact that FPC's definition is not equivalent to MS'.SpartaPascal :D
On the other hand, there is no justifiable reason _not_ to have one. This isbut there _is_ a good reason not to have one and, that is, when a programmer searches for the documentation on an API function, what shows up is MS' documentation and, calling Pascal's WriteFile as it is documented in MSDN will _not_ work and, there is _no_ Free Pascal page that documents the fact that FPC's definition is not equivalent to MS'.SpartaPascal :D
Quoteyes, an overload (using the correct definition) would definitely be a good thing in this case and, it seems its presence would not break any existing code.
Overloading more than one difference is somewhat dangerous, because people get weird errormessages if they pass e.g. a pointer and don't @ the other etc.
Normally I wouldn't mind, but by such a core procedure I get a tad conservative. It has the potential to cause problems without much gain.
Thank you for information.But I have found only one WriteFileEx (in redef.inc), where is overload?
in func.inc
function WriteFileEx(hFile:HANDLE; lpBuffer:LPCVOID; nNumberOfBytesToWrite:DWORD; lpOverlapped:LPOVERLAPPED; lpCompletio nRoutine:LPOVERLAPPED_COMPLETION_ROUTINE):WINBOOL; external 'kernel32' name 'WriteFileEx';
But by default the declaration from redef.inc is used, so this overload is still not very helpful for C-minded beginners.
QuoteIn the case of FPC, the justification is that Delphi defined it that way and for compatibility FPC followed but, it doesn't make it right.Compatibility, in the first place with existing code, is the sacred cow. We still write such things like LPVOID and wait for long pointers to return... ::)
The real problem is with the optional parameters like lpNumberOfBytesWritten.
You are supposed to pass null/nil if you do not want to obtain that information, but with a var parameter, it does not allow that directly.
What do you mean “by default”? There is no default, because it's overloaded inside the same unit and thus both are available to the user.Yes, you are right. By "default" I meant that you see the declaration from redef.inc by placing cursor over WriteFileEx in Lazarus Source Editor, and it is not obvious how to find the second one.
If one knows how, it's perfectly fine to pass a Nil to a reference parameter:I wouldn't go as far as saying it's "perfectly fine", I'd say it's definitely possible but, IMO, it should be strongly discouraged because it is completely reasonable for a procedure/function that uses "var" parameters to presume the parameters are _not_ nil. Using any of the var parameters that got passed a nil value will cause an access violation.
If one knows how, it's perfectly fine to pass a Nil to a reference parameter:I wouldn't go as far as saying it's "perfectly fine", I'd say it's definitely possible but, IMO, it should be strongly discouraged because it is completely reasonable for a procedure/function that uses "var" parameters to presume the parameters are _not_ nil. Using any of the var parameters that got passed a nil value will cause an access violation.
Finally, pragmatism dictates that modern Pascal's parameter conventions need to be compatible with C. Broadly speaking, var parameters are superior to pointers since they don't have to be explicitly dereferenced and aren't at risk from pointer arithmetic, and not allowing a var parameter to be nulled is a major omission.I completely agree that a computer language has to be compatible/accommodate C's parameter passing semantics but, I strongly believe that a "var" parameter should _not_ be nullable because, if that parameter is nullable then it should _not_ be a "var" parameter.
MarkMLl
If one knows how, it's perfectly fine to pass a Nil to a reference parameter:I wouldn't go as far as saying it's "perfectly fine", I'd say it's definitely possible but, IMO, it should be strongly discouraged because it is completely reasonable for a procedure/function that uses "var" parameters to presume the parameters are _not_ nil. Using any of the var parameters that got passed a nil value will cause an access violation.