To learn how to call DLLs, run Labs 'DLL: Writing and Using a DLL' and 'DLL: Using System DLLs (file examples)'.
A DLL is a file (usually with extension .dll) that contains procedures. J can call DLL procedures.
Win32 API system services are provided by system DLLs such as kernel32. You can also use 3rd party DLLs or DLLs you write yourself.
Script main\dll.ijs ( load 'dll'
) defines utilities for working with DLLs.
Verb cd
calls a procedure. The form is:
'filename procedure [+][%] declaration' cd parameters.
c | character (1 byte) |
s | short integer (2 byte) |
i | integer (4 byte) |
f | short floating-point (4 byte) |
d | floating point (8 byte) |
j | complex (16 byte) (not as result) |
* | pointer |
n | no result (result, if any, is ignored and 0 is returned) |
The first declaration type describes the result and the remaining ones describe the parameters in the cd
right argument.
The c i d and j types are native J types and the s and f types are not. Scalar s and f values are handled as i and d types. Pointer s and f parameters are handled as character data.
The * type is a pointer to values. A * can be followed by c s i f d or j to indicate the type of values. The DLL can read from this memory or write to it.
A scalar type (c s i f d j) must have a scalar parameter. A pointer type (* *c *s *i *f *d *j) must have either a non-scalar parameter of the right type, or a boxed scalar integer that is a memory address.
J boolean data is stored as 1 byte values. Boolean parameters are automatically converted to integers.
The mema result (Memory Management) can be used as a * type parameter. A memory address parameter is a boxed scalar. The NULL pointer is <0 .
The cd
right argument is a list of enclosed parameters. An empty vector is treated as 0 parameters and a scalar is treated as a single parameter.
The cd result is the procedure result catenated with its possibly modified right argument.
For example, the Win32 API procedure GetProfileString in kernel32 gets the value of the windows/device keyword.
a=: 'kernel32 GetProfileStringA s *c *c *c *c s' b=: 'windows';'device'; 'default'; (32$'z');32 a cd b +--+-------+------+-------+--------------------------------+--+ |31|windows|device|default|HP LaserJet 4P/4MP,HPPCL5MS,LPT |32| +--+-------+------+-------+--------------------------------+--+
The first type s indicates that the procedure returns a short integer. The first pointer names a section. The second pointer names a keyword. The third pointer is the default if the keyword is not found. The fourth parameter is where the keyword text is put. The fifth parameter is the length of the fourth parameter.
If the GetProfileStringA declaration was wrong, say a d result instead of s, it would crash your system. If the fifth parameter was 64 and the keyword was longer than the 32 characters allocated by the fourth parameter, the extra data would overwrite memory.
Procedures are usually documented with a C prototype or a Visual Basic declaration. The C prototype and VB declaration for GetProfileString are:
DWORD GetProfileString( LPCTSTR lpAppName, // address of section name LPCTSTR lpKeyName, // address of key name LPCTSTR lpDefault, // address of default string LPTSTR lpReturnedString,// address of destination buffer DWORD nSize // size of destination buffer ); Declare Function GetProfileString Lib "kernel32" Alias GetProfileStringA" ByVal lpAppName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long) As Long
J declaration types and some corresponding C and VB types are:
J | C/Visual Basic |
c | char, byte, bool |
s | short int, word, % |
i | int, long int, dword, & |
f | float, ! |
d | double, # |
* | char*, int*, LP..., void*, $ |
n | void |
cdf''
unloads all DLLs that cd
has loaded. A loaded DLL is in use and attempts to modify it will fail. If you are developing and testing a DLL you must run cdf''
before you can build and save a new version.
Release J4.02 introduced some incompatible changes:
1. scalar error results are now domain errors (cder''
provides details)
2. *m no longer supported
3. fpreset no longer always done (explicit % flag)
4. * memory address must be boxed scalar, not a scalar