Many APL+Win users have been asking for this
for a long while... it's finally here.
Here are 2 examples illustrating how to now pass API
structures to Windows calls. Assume the definitions are the following in the
APLW.INI file:
[Call]
CreateFontIndirectArray=H(*LOGFONT_ARRAY) ALIAS CreateFontIndirectA
GetClientRectArray=(HW,>L[4]) ALIAS GetClientRect
[Type]
LOGFONT_ARRAY={L,L,L,L,L,Y,Y,Y,Y,Y,Y,Y,Y,C[LF_FACESIZE]}
We use the convention (for the purpose of this example) of appending
"array" to the end of function and type names. So we've
created GetClientRectArray as a way to call
GetClientRect but with the argument specified
using array notation. The >L[4] means
a returned pointer to a four element array of 32-bit integers. In
practice the INI/ADF files are modified to specify things like LOGFONT
using array notation but without renaming it as we've done here.
In the LOGFONT_ARRAY type, we've used C[LF_FACESIZE]
rather than {C,C,C,...repeated 32 times....,C,C,C}.
Here are some examples
executed in APL using these definitions:
wcall 'CreateFontIndirectArray'
(20 0 0 0 0 0 0 0 0 0 0 0 0 'Arial')
3620
wcall 'GetClientRectArray' hwnd Ð
10 10 300 600
wcall 'GetClientRectArray' hwnd (0 0 0 0)
10 10 300 600
wcall 'GetClientRectArray' 0 (0 0 0 0 0 0)
WCALL CONVERSION ERROR: LENGTH ERROR
wcall 'GetClientRectArray' 0 (0 0 0 0 0 0)
^
The last call failed because the array was specified to only hold four
elements... six elements is not legal.
Note that in the CreateFontIndirectArray call,
we have passed the fontname argument (Arial) as a five element vector.
You might expect that we'd have to pass a 32-element vector here because
the structure it maps into specifies a 32-element mapping. But the
new structure argument features now allow you to specify any structure
using a smaller number of elements... the omitted elements are mapped
into the structure as zeros (0x00 not '0') or as the default value (using
=value following the type declaration). So, if we don't care about
the font facename, we could also have called:
wcall 'CreateFontIndirectArray' (20 0 0 0 0 0 0 0 0 0 0 0 0)
or,
wcall 'CreateFontIndirectArray' (20 0)
or,
wcall 'CreateFontIndirectArray' (,20)
but NOT as,
wcall 'CreateFontIndirectArray' 20
That last one is a quiz...
do you know why it would cause problems???
Here are some rules you'll want to know about
array notation:
- If you use array notation
in an argument list, it must be in combination with a pointer-prefix
(* or >). You cannot
use inline structures in an argument list. Array notation does NOT require a
pointer prefix when used in a structure. It is mapped inline without a pointer
prefix and by-reference (by pointer) if a prefix is specified.
- You cannot use multiple levels of array dimensions on a type.
For example, you CANNOT specify C[3][5].
- Empty or non-finite bounds are not permitted. So you cannot
specify C[] or C[0].
If you want a pointer to an un-bounded array just use pointer notation
(* or > prefix) without specifying any array dimension following
the type.
- The value specified inside the array brackets can be any constant you
could specify as an argument to the W_Const
built-in function.
- The bracket-enclosed list
must immediately follow the type name before any field name, default value, etc. So
you can specify:
C[10] TenChars
but not
C TenChars[10].
- When you specify a pointer prefix and an array suffix for the same type,
you are defining a pointer to an array rather than an array of pointers.
Therefore *C[7] means a pointer to a 7 element
character array rather than an array of 7 pointers to characters.
- An array is NOT always the same as a structure containing the same
number of elements. When the type of element in the array is simple
they are equivalent. That's the case in the LOGFONT_ARRAY
example. The C[LF_FACESIZE] is the
same as a structure of 32-C elements. However, when the type is
complex they are not the same at all. For example, RECT[3]
and {RECT,RECT,RECT} both map the same data
but they must be specified differently in the APL array used to define
them. In the first case you can specify the three instances of
rectangle data as a shape 12 vector, a shape 3 4 matrix, and empty vector,
or a shape n m matrix (where n is less than or equal to 3 and m is less
than or equal to 4). In the second case you can specify the data
as a 3 item nested array where each item contains a 4 element vector.
But a shape 12 vector, etc would not be accepted as a valid argument.
|