Calling the KI/PK Using KID (FLICK)
<<< Object-Oriented KID | Chapters | Creation of Primitives >>> |
- 4.6 KI ifail checking
- 4.7 PK error checking
- 4.8 Timing
It is possible to use the Kernel Interface Driver (KID) to call the functions in the PARASOLID kernel interface in two different ways. This chapter describes how to do this. It is assumed that the reader is familiar with LISP and with object oriented LISP.
A typical KID user need not refer to any of these functions since the higher levels of KID provides access to much of the KI/PK indirectly anyway. Those who wish to use the FLICK routines have a choice of two modes of use:
Upper case routine names (STAMOD, CRSOFA ...) map directly onto the KI routines argument by argument. These routines merely pass simple data values between FLICK and the KI/PK with no interpretation or simplification. They are therefore rather unhelpful to use and require several calls to additional support functions to interpret the results. They are made available to enable the user to overcome any restrictions imposed by the more convenient FLICK routines.
> ( STAMOD 1 3 "KID" 0 ) --> ( 1 600382 0 ) > ( CRBXSO ´( 0 0 0 ) ´( 0 0 1 ) 5 5 5 ) --> ( 7 0 ) > ( IDCOEN 7 ( token ´TYTOFA )) --> ( 69 6 0 ) > ( setq workspace ( alloc 6 )) --> @12303420 > ( GTTGLI 69 1 6 workspace ) --> ( 0 ) > ( empty 6 int workspace ) --> ( 9 23 37 48 55 72 ) |
Details of the support functions available can be found in Appendix D, "Flick Function Descriptions", of the Parasolid KI Reference Manual.
Lower case KI routine names (stamod, crsofa ...) and PK functions (pk_body_ask_faces, ... ), while primarily providing access to the equivalent KI/PK function, go to greater lengths to provide convenient output in LISP data formats. They convert integers to symbolic tokens where possible, expand arrays and KI lists as LISP lists, suppress unused arguments and ifails, and sometimes provide optional arguments with defaults.
> ( stamod ) -->V6.00.382 > ( crbxso ´( 0 0 0) ´( 0 0 1 ) 5 5 5 ) -->7 > ( idcoen 7 ´tytofa ) -->( 9 23 37 48 55 72 ) |
All the LISP KI routines are documented individually in Appendix D, "Flick Function Descriptions", of the Parasolid KI Reference Manual.
Option lists in FLICK, including associated data, are passed as an argument to the routine in a list.
A simple list of option tokens can be passed in either of these formats:
( token token token ... ) ( ( token ) ( token ) ( token ) ... ) |
Note that simple tokens in a list must either all be bracketed or all be unbracketed, these forms cannot be mixed.
Associated data is passed in a sublist with the relevant token:
( ( token real real ... ) ( token tag ... ) ( token vector ...) ... ) |
- the list can include either bracketed or unbracketed simple tokens:
( token ( token real ... ) token ( token tag ... ) ) ( ( token ) ( token real ... ) ( token ) ( token tag ... ) ) |
"options" arguments passed as lists of lists where each sub-list contains an option token together with any associated data:
> ( rrvdep ´(( RROPCT 0.000259873 1000.0 3.0 ) ( RROPSI ) ( RROPTR ) ) ( b0 tag ) nil view_matrix ) |
The documentation of the PK functions in the Parasolid PK Interface Programming Reference manual should be referred to when calling PK functions in KID.
In general, there is a LISP function for every PK function:
Options are passed to PK functions as options structures, and these are represented in LISP as a list of dotted pairs. The elements of each dotted pair are the name of a field of an options structure and the value it is to be given. For example:
> (pk_face_contains_vectors ( f0 tag ) ´(( n_vectors . 3 ) ( vectors . (( 0 0 0 ) ( 0 4 0 ) ( 0 5 0 )) )) ) |
The two following examples contain valid option structures:
However, these two examples do not:
For all the PK_BODY_create_... functions, the last received argument is a pointer to a PK_AXIS2_sf_t function which defines the local coordinate system. This may be NULL, indicating that the local and world coordinates are the same. This is indicated in LISP by leaving out the argument.
Many PK functions have return arguments of the form:
int *const n_things --- number of things PK_THING_t **const things --- things (optional) |
meaning that
things
can be set to NULL by an application if it does not want the array of things returned.
Any PK function that has such optional returns has a corresponding LISP function with optional logical arguments saying whether the array is to be returned or not. These arguments default to
t
, meaning the array is returned. However, if the argument is supplied as nil, then only the number of
things
- the length of the array - is returned:
> (pk_body_ask_faces (b0 tag)) --- returns a LISP list of faces > (pk_body_ask_faces (b0 tag) nil) --- just returns the number of faces |
Where there are several optional returns, the optional logical arguments to the LISP function are in the same order as the optional returns from the PK function. To supply an optional logical argument as nil, any others preceding it must be explicitly supplied as t or nil:
> (pk_shell_ask_oriented_faces (sh0 tag) t nil) |
In the journal file, optional logical arguments supplied as NULL or nil are journalled as @0.
Structures are represented as a list of their fields. This means that each struct adds another pair of brackets. Note the following examples:
´((0 0 0)(0 0 1)(1 0 0)) |
|
´(((0 0 0)(0 0 1)(1 0 0)) 10) |
|
´((10 20 30)) --- a struct containing a PK_VECTOR_t |
The following primitives are used by the LISP PK functions:
(list x_comp y_comp z_comp) |
|
(list low high) |
|
(list x_low y_low z_low x_high y_high z_high) |
|
(list u v) |
|
(list u_low v_low u_high v_high) |
'
)
As for s-expressions, lists which are to be passed directly to the PK/KI (without first being evaluated by LISP) should be preceded by a quote.
> ( crknpa ´( 20 22 24 ) ) |
Therefore, the quote must be omitted when elements are to be evaluated.
> ( crknpa ( list ( b0 tag ) ( b1 tag ) ( b2 tag ) ) ) |
Examples of calls which do not work because of misuse of the quote are:
> ( crknpa ( 20 22 24 ) ) > ( crknpa ( ( b0 tag ) ( b1 tag ) ( b2 tag ) ) ) > ( crknpa ´( ( b0 tag ) ( b1 tag ) ( b2 tag ) ) ) |
Like KID, FLICK performs ifail checking and raises a LISP error if a returned ifail is considered invalid. Currently this mechanism is quite different from and independent of the KID ifail processing, which is rather limited. Just which ifails are allowed may be adjusted using the support function allow_ifails. A simple example of which is:
( allow_ifails ( KI_missing_geom ) ( IDSOFF 99 ) ) |
The function allow_ifails takes any number of arguments. The first is a specification of the ifails which are valid while the remainder, which should be LISP expressions, are evaluated. The function returns the value obtained by evaluating the last argument.
Initially the only valid ifail is KI_no_errors (i.e. zero), any other ifail returned generate a LISP error. The set of valid ifails can be extended by including those which are to be allowed in the valid ifail specification either for all KI calls or - if a KI function name is given as the first element of the valid ifail list - only for that named KI function. Calls to
allow_ifails
can be nested. Once an ifail has been made valid it cannot subsequently be disallowed.
> ( allow_ifails ( KI_missing_geom ) ( IDSOFF 99 )) -- call IDSOFF but don´t produce an error if the face lacks geometry > ( allow_ifails ( STOMOD KI_modeller_not_started ) ( STOMOD )) -- stop the modeller but don´t complain if it isn´t started. > ( allow_ifails ( KI_roll_is_off ) ( my_strict_programme )) -- allow KI_roll_is_off errors, but no others > ( allow_ifails ( - KI_corrupt_file ) ( my_liberal_programme)) -- allow all errors except KI_corrupt_file > ( allow_ifails ( KI_all_ifails ) ( my_careless_programme )) -- don´t complain about anything |
For greater flexibility of use the valid ifail specification may be a list of valid ifail specifications, as in this example.
> ( allow_ifails (( IDSOFF KI_missing_geom KI_not_a_tag ) ( IDCOEN KI_missing_geom KI_not_a_tag )) ( setq v1 ( IDSOFF 99 )) ( setq v2 ( IDCOEN 100 (token ´TYTOFA) ))) |
Some lower case FLICK functions declare ifails valid like this. For example stamod permits the ifail KI_modeller_not_stopped.
valid_ifails
tries to take PK errors and KI ifails and convert the ifails into PK errors where possible, this is to try and ensure that code which uses KID functionality has similar behavior when KID calls the KI and the PK.
((define b0 p_block) x -10) (valid_ifails ´(KI_distance_le_0) ´(b0 create)) |
should trap the distance_le_0 error whether (b0 create) tries to use CRBXSO or PK_BODY_create_solid_block.
The function
valid_pk_errors
is similar to
valid_ifails
. It raises and reports the number of the first LISP error which occurs within the supplied test code:
(valid_pk_errors ´(PK_ERROR_wrong_entity) ´(pk_curve_ask_interval 12)) (valid_pk_errors ´(PK_ERROR_wrong_entity) ´(car 1)) |
Other types of error are not trapped, for example this still raises an error:
(valid_pk_errors ´(PK_ERROR_wrong_entity) ´(pk_curve_ask_interval s)) |
For multi s-expression code, use progn to prevent evaluation of the returns:
(valid_pk_errors ´(PK_ERROR_wrong_entity) ´( progn (define b0 p_block) create) (pk_curve_ask_interval (b0 tag)) ) ) |
However, this raises an error because the PK error is PK_ERROR_not_an_entity, not PK_ERROR_wrong_entity:
(valid_pk_errors ´(PK_ERROR_wrong_entity) ´( progn (undefine b0) ((define b0 p_block) create) (pk_curve_ask_interval (plus (b0 tag) 2000)) ) ) |
To allow both KI ifails and PK errors wrap the code in a valid_ifails function:
(valid_ifails ´(KI_not_a_tag) ´(valid_pk_errors ´(PK_ERROR_wrong_entity) ´( progn (undefine b0 l0) ((define b0 p_block) create) (chcken (plus (b0 tag) 2000)) (pk_curve_ask_interval (b0 tag)) ) ) ) |
Like KID, FLICK also generates a timing_line message to track each KI routine or PK function called. Some, none or all KI routine or PK functions can be traced.
The function timing controls the output of timing data for KI routine and PK function calls. It takes one argument, the timing level and returns the new level.
With no argument the current level is returned unchanged.
<<< Object-Oriented KID | Chapters | Creation of Primitives >>> |