RuleWorks

Using RuleWorks with Other Languages

Programming tasks such as computing mathematical expressions, manipulating strings, and editing large quantities of data are often easier and more efficient to develop in languages other than RuleWorks. If you are developing a RuleWorks program that needs to perform these types of tasks, you should consider using external routines. An external routine is a function or subroutine written in a language other than RuleWorks. External routines include prewritten routines such as system services and run-time library (RTL) routines.

RuleWorks allows external routines that accept arguments and return results according to the hardware platform's calling standard. This means that you can call external routines that are not written specifically for RuleWorks. Example 6-1 shows a simple RuleWorks program calling the C RTL routine, sqrt.

Example 6-1 Calling an External Routine from RuleWorks

RuleWorks also allows entry blocks to be called from other languages. Entry blocks can accept arguments and return a value. Entry blocks can call other entry blocks, but the callers must declare the other entry blocks with EXTERNAL-ROUTINE declarations. Entry blocks can even call themselves recursively.

Calling External Routines from RuleWorks

You must declare external routines before you call them in your RuleWorks program. External routines are scoped to the block in which they are declared.

The easiest way to ensure that the correct declarations have been made is to place the EXTERNAL-ROUTINE declarations in a separate declaration block and have each module acquire the compiled declarations via a USES clause. See Chapter 5 for details on data partitioning and declaration sharing.

The complete syntax for the EXTERNAL-ROUTINE declaration is shown below:

Figure 6-1. External Routine Declaration Syntax

(EXTERNAL-ROUTINE routine-name

The routine-name is required; the ALIAS-FOR, ACCEPTS and RETURNS clauses are optional. The syntax for calling an external routine is shown below:

EXTERNAL-ROUTINE declarations may appear inside any type of block, but they must appear inside of some kind of block, and they must appear before they are used. Duplicate declarations of the same external routine will generate a warning and be ignored so long as the declarations are identical.

External routines that return a value can be used on the RHS (as shown in Example 6-1) or on the LHS. External routines that do not return a value must be used on the RHS as if they were RuleWorks actions. You can also call an external routine that does return a value as if it were an RHS action, but in this case RuleWorks ignores the return value.

Writing Portable Code

The ALIAS-FOR clause allows you to declare that the routine name used inside RuleWorks is not the actual name that will be linked. This is useful for mapping a case-sensitive external routine name onto a case-insensitive RuleWorks symbol.

The actual function name must be quoted to preserve case. For example:

You can use at most one ALIAS-FOR clause in an EXTERNAL-ROUTINE declaration. You must provide exactly one function name in an ALIAS-FOR clause.

Passing Parameters

Use the ACCEPTS clause to declare one or more parameters for an external routine. The <formal-parameter-name> is optional; use it to help make your code more self-documenting. The external-type-name is required. The passing-mechanism for each argument is also optional; the default mechanism for each external type is shown in Table 6-1. Arrays of each type are also allowed, passed BY REFERENCE only.

Table 6-1. External Data Types and Argument-Passing Mechanisms

Argument Passing Mechanisms
External
Data Type
BY VALUEBY REFERENCE
READ-ONLY
BY REFERENCE
READ-WRITE
BYTEDefaultÖÖ
SHORTDefaultÖÖ
LONGDefaultÖÖ
UNSIGNED-BYTEDefaultÖÖ
UNSIGNED-SHORTDefaultÖÖ
UNSIGNED-LONGDefaultÖÖ
SINGLE-FLOAT(1)DefaultÖÖ
DOUBLE-FLOAT(2)DefaultÖÖ
ASCIZN/SDefaultÖ
ASCIDN/SDefaultÖ
POINTER(3)DefaultÖÖ
ATOM(4)DefaultÖÖ

(1) On VMS systems, SINGLE-FLOAT refers to F_float_data

(2) On VAX VMS systems, DOUBLE-FLOAT refers to D_float data; on OpenVMS for Alpha AXP systems, DOUBLE-FLOAT refers to G_float data.

(3) Opaque virtual address

(4) Opaque atom

ÖSupported, but not the default

N/S Not supported

Numeric and pointer external types default to zeros. ASCIZ and ASCID externals default to the zero-length string. The ATOM external defaults to NIL.

RuleWorks's compound values correspond to an array of atoms in external routines. You declare a parameter as an array by putting brackets ( [ ] ) between the formal parameter name and the external data type. If you do not declare the size of the array by putting an integer between the brackets, then the array received by the external routine has as many elements as the compound value had when it was passed out, and the external routine cannot change the size of the array. An array returned by an external routine must be the declared size.

Since the size of the array is not automatically passed, applications using empty brackets must define a convention such as a specific value to signal the end of the array, or pass the length as a separate parameter. Example 6-2 shows a C program that passes a compound value.

Example 6-2 Passing a Compound Value: C Function

Example 6-3 shows the RuleWorks program that calls the C function in Example 6-2.

Example 6-3 Passing a Compound Value: RuleWorks Program