# About OPXs

## Contents

- OPX header files
- Compatibility
- Callbacks from OPX procedures

OPL can use language extensions provided in separate DLLs written specially for OPL support. These DLLs have the file extension `.opx`.

It is not within the scope of this manual to cover how to develop OPXs yourself, as it requires knowledge of the C++ language. If you require details of how to do this, you should obtain a copy of the EPOC C++ Software Development Kit (SDK) from Symbian Ltd.

A maximum of 255 OPXs can be used in any one OPL module and any OPX may have up to 65535 procedures defined in it. If these values are exceeded then errors are reported at translate-time (see Error Handling).

With OPXs, the OPL programmer is sometimes given direct access to objects via pointers (for efficiency). Otherwise sprites, for example, could not be set up using an array of IDs. These objects can be explicitly deleted to free memory or else they will be deleted when the program exits.

## OPX header files

The OPX supplier provides an OXH header file. This provides the declaration for the OPX, specifying its name UID and version number (see below), followed by its procedure prototypes.

The new `INCLUDE` keyword is used to include these header files. Alternatively, the declaration can be inserted directly into the OPL file, i.e.

        DECLARE OPX <opxName>,<uid>,<version>
              <protoType1> : <ordinal1>
              <protoType2> : <ordinal2>
              ...
        END DECLARE

where,

`<name>` is the name of the OPX without the .OPX extension. The OPX is stored in a `\System\Opx\` folder on any drive, with the drives scanned from `Y:` to `A:` and then `Z:` if no path is specified. This allows ROM OPXs (in `Z:`) to be overridden if required.

`<uid>` is the UID of the OPX. The specification of a UID as well as a name guards against OPXs being with the same name being confused, which could otherwise cause serious problems. The UID is checked on loading the OPX and a ‘Not supported’ error will result if the UIDs in the header file and in the OPX itself do not match.

`<version>` is the version number of the OPX. The version number of an OPX will be increased when any new procedures are added. OPL will refuse to load an OPX which reports that it can’t support the version number given in the declaration. The version number expressed in hex is e.g. $0100 to represent version 1.00, $0102 for version 1.02 etc. In general, an OPX supplier will increment the 2 low digits (the so-called minor version number) for backward compatible changes, and will increment the 2 high digits for major incompatible changes.

`<prototype>` specifies the name, return type and parameters of an OPX procedure in the same way as for an OPL procedure when using the `EXTERNAL` keyword. Numeric parameters to OPX procedure can be passed by reference using `BYREF`. This means that the value of the variable can be changed by the OPX procedure. The OPX procedure prototype is followed additionally by a colon and then the

`<ordinal>` specifies the ordinal number of the procedure in the OPX itself. This is used to call the correct procedure, i.e. the OPX is linked by ordinal.

If an OPX procedure name clashes with one of your OPL procedures, or with that of another OPX procedure, you can make a copy of the OXH file and change the name of the offending procedures, but not the return type, parameter list or ordinal. You should then include this new OXH file in your module and the new name can then be used to refer to the procedure in your code.

For example, consider the OPX declaration,

        DECLARE OPX XXOpx,XXOpxUid&,XXOpxVersion&
              XXClose%:(id&) : 1
              ProcWithLongParam:(aLong&) : 2
              AddOneToParams:(BYREF par1%,BYREF par2&, BYREF par3) : 3
        END DECLARE

If a short integer is passed to `ProcWithLongParam:`, the translator will automatically convert it to a long integer.

The `AddOneToParams:` procedure adds one to each of the parameters. This is possible because the parameters are passed by reference using BYREF. Parameters passed by reference must be variables rather than constant values because the OPX will write back to the variable. The variable type must always be the same as given in the declaration.

## Compatibility

ER5 WINS OPXs are not useable on the ER3 EPOC Emulator, and ER3 WINS OPXs will not work on the ER5 Emulator. However, ER5 MARM OPXs will work on ER3 EPOC devices, and ER3 MARM OPXs will work under ER5.

## Callbacks from OPX procedures

An OPX procedure can call back to a module procedure. This is often useful if the OPX needs some information that is not known when the OPX procedure is initially called, or if it requires a large amount of data which needs to be sent piecemeal.

The OPX provider will specify the exact form of the procedure which you must provide.

Note that `STOP` may not be used during an OPX callback and will raise the error ‘`STOP used in callback`’ if it is. See `STOP` in Keyword Reference.