Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2002-11

When to use pointers with win32

14 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Hans Mårtensson

Currently I am trying to learn windows programming with Free Pascal, but I've got a problem with how to use the win32 unit and the (mmsystem unit as well). The Free Pascal web site informs that the win32 unit implements all the windows APIs, and refers to Microsoft or Delphi for further documentation. But the documentation found there is written for C programming. My problem is translating this into Pascal, due to the difference between C and Pascal in using parameters in procedure calls.

Here is an example to explain what I mean:

In Pascal a procedure call like �someproc(data)' will pass either the value of data OR the pointer to the data to the procedure, depending of how the procedure is declared.

If the procedure is declared as:
�Procedure someproc(data: sometype)'
then the value of the data will be passed

but if the procedure is declared as:
�Procedure someproc(var data: sometype)'
the the pointer to the data will be passed.

Whereas in C, you can only pass values to the procedure (or function). Of course it is possible to pass the pointer, but then you have to know this, when calling the procedure. Your program line must be �someproc(&data)' for passing the pointer.

When I read the documentation of the windows API, for each parameter in any function it tells me whether I should pass the value or the pointer. So in case of writing a C-program, there is no problem. But when using Pascal with the win32 unit, I think it must be different. It would be a little weird and agaist the beauty of Pascal to define a lot of pointers to be used with this unit. So my guess is that the win32 unit has been constructed as to use Pascal style procedure calls, so that �someproc(data)' sometimes pass the pointer to the data, namely when the API wants the pointer. But does that always hold?
In the examples that comes with the Free Pascal installation, I have seen that sometimes the address operator @ is used in a call to a procedure in the win32 unit.

So my question is: How can I know when to use the data identifier and when to use an address or pointer in a call to a procedure in the win32 unit?

Hans Maartensson

Marco van de Voort
to Hans Mårtensson
Show quoted text 15 lines
but if the procedure is declared as: �Procedure someproc(var data: sometype)' the the pointer to the data will be passed. Whereas in C, you can only pass values to the procedure (or function). Of course it is possible to pass the pointer, but then you have to know this, when calling the procedure. Your program line must be �someproc(&data)' for passing the pointer. When I read the documentation of the windows API, for each parameter in any function it tells me whether I should pass the value or the pointer. So in case of writing a C-program, there is no problem. But when using Pascal with the win32 unit, I think it must be different. It would be a little weird and agaist the beauty of Pascal to define a lot of pointers to be used with this unit.

We also fell for this trap, but in general it is wisest to keep the pointers. This because many win32 (and also POSIX) routines accept a NIL pointer as special value (often meaning something like use default for this parameter).

Show quoted text 10 lines
So my guess is that the win32 unit has been constructed as to use Pascal style procedure calls, so that �someproc(data)' sometimes pass the pointer to the data, namely when the API wants the pointer. But does that always hold? In the examples that comes with the Free Pascal installation, I have seen that sometimes the address operator @ is used in a call to a procedure in the win32 unit. So my question is: How can I know when to use the data identifier and when to use an address or pointer in a call to a procedure in the win32 unit?

Check the source of the definition. Most are pointers, but some are not because Delphi decided to use const and var.

If you really hate the C specifications of the win32 api, try to find the (somewhat old) win32 helpfile on the Borland site. I don't have an URL since they frequently reorder things.

Peter Vreman
to Marco van de Voort
Show quoted text 48 lines
> but if the procedure is declared as: > ‘Procedure someproc(var data: sometype)' > the the pointer to the data will be passed. > > Whereas in C, you can only pass values to the procedure (or function). > Of > course it is possible to pass the pointer, but then you have to know > this, > when calling the procedure. Your program line must be ‘someproc(&data)' > for > passing the pointer. > > When I read the documentation of the windows API, for each parameter in > any > function it tells me whether I should pass the value or the pointer. So > in > case of writing a C-program, there is no problem. But when using Pascal > with the win32 unit, I think it must be different. It would be a little > weird and agaist the beauty of Pascal to define a lot of pointers to be > used with this unit. We also fell for this trap, but in general it is wisest to keep the pointers. This because many win32 (and also POSIX) routines accept a NIL pointer as special value (often meaning something like use default for this parameter). > So my guess is that the win32 unit has been > constructed as to use Pascal style procedure calls, so that > ‘someproc(data)' sometimes pass the pointer to the data, namely when the > API wants the pointer. But does that always hold? > In the examples that comes with the Free Pascal installation, I have > seen > that sometimes the address operator @ is used in a call to a procedure > in > the win32 unit. > > So my question is: How can I know when to use the data identifier and > when > to use an address or pointer in a call to a procedure in the win32 unit? Check the source of the definition. Most are pointers, but some are not because Delphi decided to use const and var. If you really hate the C specifications of the win32 api, try to find the (somewhat old) win32 helpfile on the Borland site. I don't have an URL since they frequently reorder things.

The header files are translated from C. Where Delphi defined a definition with const or var parameters then that version is added as an overloaded definition. So you can use both the C calling with passing the address. Or use the Delphi way with passing a value to a var parameter

Hans Mårtensson
to Peter Vreman
you wrote 5 lines
The header files are translated from C. Where Delphi defined a definition with const or var parameters then that version is added as an overloaded definition. So you can use both the C calling with passing the address. Or use the Delphi way with passing a value to a var parameter
OK that makes sense, but then again: The following line:
waveInThread := CreateThread(0, 0, @waveInProc, 0, 0, @threadID);

gives me the compiler error:
Incompatible type for arg no. 6: Got VOID_POINTER, expected ULONG

whereas the line:
waveInThread := CreateThread(0, 0, @waveInProc, 0, 0, threadID); compiles with no errors.

??
(threadID is declared as cardinal)

Hans Maartensson

med venlig hilsen
Hans Mårtensson

Hans Mårtensson
to Marco van de Voort: We also fell for this trap, but in general it is wisest to keep the pointers. This…
you wrote
If you really hate the C specifications of the win32 api, try to find the (somewhat old) win32 helpfile on the Borland site. I don't have an URL since they frequently reorder things.

I don't hate C, I just like Pascal better and find it easier to use, but I have some problem with the intermixing :-)
I've got a win32.hlp from Borland, but it speeks C.

Hans Maartensson

Florian Klaempfl
to Hans Mårtensson
you wrote 8 lines
At 00:35 25-11-02 +0100, you wrote: >If you really hate the C specifications of the win32 api, try to find the >(somewhat old) win32 helpfile on the Borland site. I don't have an URL since >they frequently reorder things. > I don't hate C, I just like Pascal better and find it easier to use, but I have some problem with the intermixing :-) I've got a win32.hlp from Borland, but it speeks C.

Even Borland doesn't have a pascalish win32.hlp.

Peter Vreman
to Hans Mårtensson: OK that makes sense, but then again: The following line: waveInThread := CreateThread(0,…
Show quoted text 20 lines
At 07:21 25-11-02 +0100, you wrote: >The header files are translated from C. Where Delphi defined a definition >with const or var parameters then that version is added as an overloaded >definition. So you can use both the C calling with passing the address. > Or >use the Delphi way with passing a value to a var parameter > OK that makes sense, but then again: The following line: waveInThread := CreateThread(0, 0, @waveInProc, 0, 0, @threadID); gives me the compiler error: Incompatible type for arg no. 6: Got VOID_POINTER, expected ULONG whereas the line: waveInThread := CreateThread(0, 0, @waveInProc, 0, 0, threadID); compiles with no errors. ?? (threadID is declared as cardinal)

That is because the CreateThread() with C calling is accidently removed from the windows unit.

Hans Mårtensson
to Peter Vreman
you wrote 14 lines
> The following line: > waveInThread := CreateThread(0, 0, @waveInProc, 0, 0, @threadID); > > gives me the compiler error: > Incompatible type for arg no. 6: Got VOID_POINTER, expected ULONG > > whereas the line: > waveInThread := CreateThread(0, 0, @waveInProc, 0, 0, threadID); > compiles with no errors. > That is because the CreateThread() with C calling is accidently removed from the windows unit.

As far I can see, your explanations are wrong, because the CreateThread function is documented in then win32.hlp as to require as the 6th parameter an 'address of returned thread identifier'. But the lines

var pthreadID: ^cardinal;
...
waveInThread := CreateThread(0, 0, @waveInProc, 0, 0, pthreadID);

gives the compiler error:
Incompatible type for arg no. 6: Got ^ULONG, expected ULONG

whereas the lines:

var threadID: cardinal;
...
waveInThread := CreateThread(0, 0, @waveInProc, 0, 0, threadID);

compiles with no error.

This shows that I cannot call the original CreateThread API, but only a Pascal style redefined function (which actually passes the pointer to the threadID, because the function will set the value for me).

So I still ask for how to find information about the Pascal definitions in the windows unit.

Jonas Maebe
to Hans Mårtensson
Hans Mårtensson wrote 23 lines
> That is because the CreateThread() with C calling is accidently > removed > from the windows unit. > As far I can see, your explanations are wrong, because the CreateThread function is documented in then win32.hlp as to require as the 6th parameter an 'address of returned thread identifier'. But the lines var pthreadID: ^cardinal; ... waveInThread := CreateThread(0, 0, @waveInProc, 0, 0, pthreadID); gives the compiler error: Incompatible type for arg no. 6: Got ^ULONG, expected ULONG whereas the lines: var threadID: cardinal; ... waveInThread := CreateThread(0, 0, @waveInProc, 0, 0, threadID); compiles with no error.

This shows that what Peter said above is correct: the Pascal version (where the sixth parameter is a "var threadid: cardinal") is there, but the C version (where the sixth parameter should be "threadid: ^cardinal") is missing.

Jonas

Unknown author
Show quoted text 25 lines
As far I can see, your explanations are wrong, because the CreateThread function is documented in then win32.hlp as to require as the 6th parameter an 'address of returned thread identifier'. But the lines var pthreadID: ^cardinal; .... waveInThread := CreateThread(0, 0, @waveInProc, 0, 0, pthreadID); gives the compiler error: Incompatible type for arg no. 6: Got ^ULONG, expected ULONG whereas the lines: var threadID: cardinal; .... waveInThread := CreateThread(0, 0, @waveInProc, 0, 0, threadID); compiles with no error. This shows that I cannot call the original CreateThread API, but only a Pascal style redefined function (which actually passes the pointer to the threadID, because the function will set the value for me). So I still ask for how to find information about the Pascal definitions in the windows unit.

Delphi's definition is:

function CreateThread(lpThreadAttributes: Pointer;
  dwStackSize: DWORD; lpStartAddress: TFNThreadStartRoutine;
  lpParameter: Pointer; dwCreationFlags: DWORD; var lpThreadId: DWORD):
THandle; stdcall;

DWORD = Cardinal for our purposes (longword is more correct I guess.)

This tells me that for compatibilitys sake, and Pascal readability (i.e. no pointers) is the version I would like to have to use (and do.)

Matt

---------------------------------------------
This message was sent using Mistral WebMail.
http://www.mistral.co.uk/

Hans Mårtensson
to Unknown author
you wrote 16 lines
> .... > So I still ask for how to find information about the Pascal definitions in > the windows unit. Delphi's definition is: function CreateThread(lpThreadAttributes: Pointer; dwStackSize: DWORD; lpStartAddress: TFNThreadStartRoutine; lpParameter: Pointer; dwCreationFlags: DWORD; var lpThreadId: DWORD): THandle; stdcall; DWORD = Cardinal for our purposes (longword is more correct I guess.) This tells me that for compatibilitys sake, and Pascal readability (i.e. no pointers) is the version I would like to have to use (and do.)

OK, this is in agreement with what I found out by trial and error. My main interest right now is to achieve this kind of information about all the function in the windows unit (and the mmsystem unit) (because trial and error is a slow proces). Of course it is a part of the documentation for the Delphi system, but I haven't got the Delphi.
Are these definitions available for free? Where?

med venlig hilsen
Hans Mårtensson

Peter Vreman
to Hans Mårtensson
Show quoted text 27 lines
At 15:40 26-11-02 GMT, you wrote: >> .... >> So I still ask for how to find information about the Pascal definitions >> in >> the windows unit. > >Delphi's definition is: > >function CreateThread(lpThreadAttributes: Pointer; > dwStackSize: DWORD; lpStartAddress: TFNThreadStartRoutine; > lpParameter: Pointer; dwCreationFlags: DWORD; var lpThreadId: DWORD): >THandle; stdcall; > >DWORD = Cardinal for our purposes (longword is more correct I guess.) > >This tells me that for compatibilitys sake, and Pascal readability (i.e. > no >pointers) is the version I would like to have to use (and do.) > OK, this is in agreement with what I found out by trial and error. My main interest right now is to achieve this kind of information about all the function in the windows unit (and the mmsystem unit) (because trial and error is a slow proces). Of course it is a part of the documentation for the Delphi system, but I haven't got the Delphi. Are these definitions available for free? Where?

They are freely available in the sources of the windows unit :-) There is no helpfile or whatever available. It's way too much work to create such a helpfile/reference manual

Hans Mårtensson
to Peter Vreman: They are freely available in the sources of the windows unit :-) There is no helpfile or…
you wrote 7 lines
> Are these definitions available for free? Where? > They are freely available in the sources of the windows unit :-) There is no helpfile or whatever available. It's way too much work to create such a helpfile/reference manual

Oh, is it that simple ...
I have only looked at the pp\source\rtl\win32\windows.pp, and it wasn't much help by itself.
Now I looked in the inc-files and found the wanted createThread definition in inc\redef.inc, so I can see, I must look at all the inc-files.

Thank you very much, everybody who has bothered about answering my questions. It has helped a lot. Also thanks to Mikael Bak, who gave me an URL, which I will check out as the next thing.

Hans Maartensson