topheader Welcome 3.129.67.26 @ xps.scios.ch on Thu Apr 25 20:41:17 UTC 2024
 
topheader
 

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

clips:apg3 [2010/01/04 20:31] (current)
admin created
Line 1: Line 1:
 +====== Section 5   Creating a CLIPS Run time Program ======
 +
 +===== 5.1 Compiling the Constructs =====
 +
 +This section describes the procedure for creating a CLIPS run time module. A run time program compiles all of the constructs (defrule, deffacts, deftemplate,​ etc.) into a single executable and reduces the size of the executable image. A run-time program will not run any faster than a program loaded using the **load** or **bload** commands. The **constructs-to-c** command used to generate a run-time program creates files containing the C data structures that would dynamically be allocated if the **load**; or **bload** command was used. With the exception of some initialization routines, the **constructs-to-c** command does not generate any executable code. The primary benefits of creating a run-time program are: applications can be delivered as a single executable file; loading constructs as part of an executable is faster than loading them from an text or binary file; the CLIPS portion of the run-time program is smaller because the code needed to parse constructs can be discarded; and less memory is required to represent your program’s constructs since memory for them is statically rather than dynamically allocated.
 +
 +\\ Creating a run time module can be achieved with the following steps:
 +
 +\\ 1) Start CLIPS and load in all of the constructs that will constitute a run time module. Call the **constructs to c** command using the following syntax:
 +
 +\\ (constructs to c <​file name>​ <id> [<​max-elements>​])
 +
 +\\ where <​file name>​ is a string or a symbol, <id> is an integer, and the optional argument <​max-elements>​ is also an integer. For example, if the construct file loaded was named "​expert.clp",​ the conversion command might be
 +
 +\\ (constructs to c exp 1)
 +
 +\\ This command would store the converted constructs in several output files ("​exp1_1.c",​ "​exp1_2.c",​ ... , "​exp7_1.c"​) and use a module id of 1 for this collection of constructs. The use of the module id will be discussed in greater detail later. Once the con­version is complete, exit CLIPS. For large systems, this output may be //very// large (> 200K). It is possible to limit the size of the generated files by using the <​max elements>​ argument. This argument indicates the maximum number of structures which may be placed in a single array stored in a file. Where possible, if this number is exceeded new files will be created to store additional information. This feature is useful for compilers that may place a limitation on the size of a file that may be compiled.
 +
 +\\ Note that the .c extension is added by CLIPS. When giving the file name prefix, users should consider the maximum number of characters their system allows in a file name. For example, under MS DOS, only eight characters are allowed in the file name. For very large systems, it is possible for CLIPS to add up to 5 characters to the file name prefix. Therefore, for system which allow only 8 character file names, the prefix should be no more than 3 characters.
 +
 +\\ Constraint information associated with constructs is not saved to the C files generated by the **constructs-to-c** command unless dynamic constraint checking is enabled (using the **set-dynamic-constraint-checking** command).
 +
 +\\ The **constructs to c** command is not available in the standard CLIPS distribution executable. Users wishing to create a run-time program must recompile CLIPS to include this capability (see section 2.2 for information on tailoring CLIPS and the CONSTRUCT_COMPILER setup flag).
 +
 +\\ 2) Set the RUN_TIME setup flag in the **setup.h** header file to 1 and compile all of the c files just generated.
 +
 +\\ 3) Modify the **main.c** module for embedded operation. Unless the user has other specific uses, the argc and argv arguments to the main function should be elimi­nated. The function **InitializeEnvironment** should not be called. Also do //not// call the **CommandLoop** or **RerouteStdin** functions which are normally called from the **main** function of a command line version of CLIPS. Do //not// define any functions in the **UserFunctions** function. The function **UserFunctions** is not called during initialization. All of the function definitions have already been compiled in the '​C'​ constructs code. In order for your run-time program to be loaded, a function must be called to initialize the constructs module. This function is defined in the '​C'​ constructs code, and its name is dependent upon the id used when translating the constructs to '​C'​ code. The name of the function is **InitCImage****_<​id>​** where <id> is the integer used as the construct module <id>. In the example above, the function name would be **InitCImage_1**. The return value of this function is a pointer to an environment (see section 9) which was created and initialized to contain your run-time program. This initialization steps probably would be followed by any user initialization,​ then by a reset and run. Finally, when you are finished with a run-time module, you can call **DestroyEnvironment** to remove it. An example **main.c** file would be
 +
 +\\ #include <​stdio.h>​\\ #include "​clips.h"​\\ \\ main()\\ {
 +
 +void *theEnv;
 +
 +\\ theEnv = InitCImage_1();​
 +
 +•\\ • %%/*%% Any user Initialization %%*/%%\\ •\\ EnvReset(theEnv);​
 +
 +EnvRun(theEnv,​-1);​
 +
 +•\\ • %%/*%% Any other code %%*/%%\\ •
 +
 +DestroyEnvironment(theEnv);​\\ }
 +
 +\\ UserFunctions()\\ {
 +
 +%%/*%% UserFunctions is not called for a run-time version. %%*/%%
 +
 +}
 +
 +\\ 4) Recompile all of the CLIPS source code (the RUN_TIME flag should still be 1). This causes several modifications in the CLIPS code. The run time CLIPS module does not have the capability to load new constructs. Do NOT change any other compiler flags! Because of the time involved in recompiling CLIPS, it may be appropriate to recompile the run time version of CLIPS into a separate library from the full ver­sion of CLIPS.
 +
 +\\ 5) Link all regular CLIPS modules together with any user defined function modules and the '​C'​ construct modules. Make sure that any user-defined functions have global scope. //Do not// place the construct modules within a library for the purposes of linking (the regular CLIPS modules, however, can be placed in a library). Some linkers (most notably the VAX VMS linker) will not correctly resolve references to global data that is stored in a module consisting only of global data.
 +
 +\\ 6) The run time module which includes user constructs is now ready to run.
 +
 +\\ Note that individual constructs may not be added or removed in a run time environment. Because of this, the **load** function is not available for use in run-time programs. The clear command will also not remove any constructs (although it will clear facts and instances). Use calls to the InitCImage­_... functions to clear the environment and replace it with a new set of constructs. In addition, the **eval** and **build** functions do not work in a run time environment.
 +
 +\\ Since new constructs can’t be added, a run-time program can’t dynamically load a deffacts or definstances construct. To dynamically load facts and/or instances in a run-time program, the CLIPS **load-facts** and **load-instances** functions or the C **LoadFacts** and **LoadInstances** functions should be used in place of deffacts and definstances constructs.
 +
 +\\ **Important Note**
 +
 +In prior versions of CLIPS, it was possible to switch between different images by calling the **InitCImage** function of the desired run-time program while execution was halted. This mechanism is no longer available. Each call to separate **InitCImage** functions creates a unique environment into which the run-time program is loaded. You can thus switch between various runtime programs by using the environment API to specify which environment is the target of a command. Also note that only the first call to a given **InitCImage** function will create an environment containing the specified run-time program. Subsequent calls have no effect and a value of NULL is returned by the function. Once the **DestroyEnvironment** function has been called to remove an environment created by an **InitCImage** call, there is no way to reload the run time program.
 +
 +\\ ====== Section 6   Combining CLIPS with Languages Other Than C ======
 +
 +CLIPS is developed in C and is most easily combined with user functions written in C. However, other languages can be used for user defined functions, and CLIPS even may be embedded within a program written in another language. Users wishing to embed CLIPS with Ada should consider using CLIPS/Ada (see the //​CLIPS/​Ada//​ //Advanced Programming Guide//).
 +
 +===== 6.1 Introduction =====
 +
 +This section will describe how to combine CLIPS with Ada or FORTRAN routines. Specific code examples will be used to illustrate the con­cepts. The code used in these examples is valid for VAX VMS systems which have the DEC C compiler, the DEC FORTRAN compiler, and the DEC Ada compiler.
 +
 +\\ Three basic capabilities are needed for complete language mixing.
 +
 +\\ • A program in another language may be used as the main program.
 +
 +\\ • The C access functions to CLIPS can be called from the other language and have parameters passed to them.
 +
 +\\ • Functions written in the other language can be called by CLIPS and have parameters passed to them.
 +
 +\\ The integration of CLIPS (and C) with other languages requires an understanding of how each language passes parameters between routines. In general, interface functions will be needed to pass parameters from C to another language and from another language to C. The basic concepts of mixed language parameter passing are the same regardless of the language or machine. However, since every machine and op­erating system passes parameters differently,​ specific details (and code) may differ from machine to machine. To improve usability and to minimize the amount of recoding needed for each ma­chine, interface packages can be developed which allow user routines to call the standard CLIPS embedded command functions. The details of passing information //from// external routines to CLIPS generally are handled inside of the interface package. To pass parameters from CLIPS //to// an external routine, users will have to write inter­face functions. Example interface packages for VMS FORTRAN and VMS Ada to selected CLIPS functions are listed in appendix A. Section 6.9 will discuss how to construct an interface package for other machines/​compilers.
 +
 +===== 6.2 Ada and FORTRAN Interface Package Function List =====
 +
 +The Ada and FORTRAN interface packages in appendix A provide many of the embedded CLIPS commands discussed in section 4 of this manual. Each function in the interface package prepends an //x// to the beginning of the corresponding C function name. A list of the C functions and their FORTRAN or Ada corollaries which are provided in the interface packages listed in the appendices appears below.
 +
 +\\ | **C Function** | **Ada/​FORTRAN Function** |
 +| InitializeEnvironment | xInitializeEnvironment |
 +| Reset | xReset |
 +| Load | xLoad |
 +| Run | xRun |
 +| Facts | xFacts |
 +| Watch | xWatch |
 +| Unwatch | xUnwatch |
 +| AssertString | xAssertString |
 +| Retract | xRetract |
 +| PrintRouter | xPrintRouter |
 +| FindDefrule | xFindDefrule |
 +| Undefrule | xUndefrule |
 +
 +\\ The arguments to these functions are the same as described in section 4, however, the corresponding data type in either Ada or FORTRAN should be passed as a parameter. For example, when using Ada, the function xLoad should be passed an Ada string, not a C string (the function xLoad will perform the conversion). FORTRAN function names defined above do //not// follow ANSI 77 name standards. The VMS FORTRAN implementation described in this section allows long function names.
 +
 +===== 6.3 Embedded CLIPS   Using an External Main Program =====
 +
 +Any program may be used as the main program for embedded CLIPS application;​s. The main program works essentially the same as in C.
 +
 +__**Example Ada Main Program**__
 +
 +with CLIPS; use CLIPS;
 +
 +\\ with TEXT_IO; use TEXT_IO;
 +
 +\\ procedure MAIN is
 +
 +\\ File_Name : string (1..50);
 +
 +File_Open_Status : integer;
 +
 +Rules_Fired : integer;
 +
 +\\ begin
 +
 +\\ xInitializeEnvironment;​
 +
 +\\ File_Name (1..7) := "​mab.clp";​
 +
 +-- Load rules
 +
 +File_Open_Status := xLoad (File_Name);​
 +
 +\\ if File_Open_Status = 1 then
 +
 +xReset;
 +
 +Rules_Fired := xRun (-1);
 +
 +PUT (integer'​IMAGE (Rules_Fired));​
 +
 +PUT_LINE (" Rules Fired"​);​
 +
 +else
 +
 +PUT_LINE ("​Unable to open rules file"​);​
 +
 +end if;
 +
 +\\ end MAIN;
 +
 +__**Example FORTRAN Main Program**__
 +
 +PROGRAM MAIN
 +
 +C
 +
 +INTEGER xLoad, FILE_OPEN_STATUS
 +
 +CHARACTER *8 FILE_NAME
 +
 +INTEGER xRun, RULES_FIRED
 +
 +C
 +
 +CALL xInitializeEnvironment
 +
 +C
 +
 +FILE_NAME = '​mab.clp'​
 +
 +FILE_OPEN_STATUS = xLoad (FILE_NAME)
 +
 +\\ IF (FILE_OPEN_STATUS .EQ. 1) THEN
 +
 +CALL xReset
 +
 +RULES_FIRED = xRun (-1)
 +
 +WRITE (6,100) RULES_FIRED
 +
 +ELSE
 +
 +WRITE (6,101)
 +
 +END IF
 +
 +\\ 100 FORMAT (I8,' RULES FIRED'​)
 +
 +101 FORMAT %%('%% UNABLE TO OPEN RULES FILE')
 +
 +STOP
 +
 +END
 +
 +\\ SUBROUTINE UserFunctions
 +
 +RETURN
 +
 +END
 +
 +===== 6.4 Asserting Facts into CLIPS =====
 +
 +An external function may assert a fact into CLIPS by calling **xAssertString**. External functions also may retract a fact previously asserted from outside of CLIPS. Note that the parameter passed to xRetract must have been received from a call to xAssertString. Any other value will cause unpredictable results.
 +
 +__**Ada Example**__
 +
 +Fact_Pointer : integer;\\ Not_Previously_Retracted : boolean;\\ \\ Fact_Pointer := xAssertString ("​dummy hello"​);​\\ Not_Previously_Retracted := xRetract (Fact_Pointer);​
 +
 +__**FORTRAN Example**__
 +
 +CHARACTER *20 FACT_STRING
 +
 +INTEGER xAssertString,​ FACT_POINTER\\ INTEGER xRetract, NOT_PREVIOUSLY_RETRACTED\\ \\ 
 +
 +FACT_STRING = 'dummy hello'​\\ FACT_POINTER = xAssertString (FACT_STRING)\\ NOT_PREVIOUSLY_RETRACTED = xRetract (FACT_POINTER)
 +
 +===== 6.5 Calling a Subroutine from CLIPS =====
 +
 +Like any other user defined functions, subroutines written in other languages may be called from CLIPS. Depending on the language, the return value from the function call may or may not be useful. For example, most FORTRAN imple­mentations allow a return value from a function but not from a subroutine. In these in­stances,​ the subroutine may be called for side effect only. As with defined functions written in C, the user must create an entry in **UserFunctions** for the subroutine (see section 3.1;). An **extern** defi­nition also must appear in the same file as the **UserFunctions** function, defining the type of data that the function will return. If the function does not return a value (Ada procedures or FORTRAN subroutines),​ it should be defined as returning a void value. See section 3.1 for the allowed return values for user defined functions.
 +
 +__**Ada Example**__
 +
 +1:procedure DISPLAY is\\ 2:   Standard Ada definitions and declarations\\ 3:begin\\ 4:  \\ 5:   Any kind of normal Ada code may be used\\ 6:  \\ •\\ •\\ •\\ 7:  \\ 8:end DISPLAY;
 +
 +__**FORTRAN Example**__
 +
 +subroutine display\\ C\\ C Any kind of normal FORTRAN code may be used\\ C\\ •\\ •\\ •\\ C\\ return\\ end
 +
 +__**UserFunctions entry for either example**__
 +
 +extern void display();​\\ \\ UserFunctions()\\ {\\ DefineFunction("​display",'​v',​PTIF display,"​display"​);​\\ •\\ •\\ •\\ %%/*%% Any other user-defined functions. %%*/%%\\ •\\ •\\ •\\ }
 +
 +===== 6.6 Passing Arguments from CLIPS to an External Function =====
 +
 +Arguments may be passed from CLIPS to an external function. CLIPS does not actually pass arguments to the function; instead arguments must be pulled from internal CLIPS buffers by using the functions described in section 3. Although the argument access functions could be called directly from Ada or FORTRAN, it probably is easier to write an interface function in C. CLIPS will call the C routine, which gathers the arguments and passes them in the proper manner to the external sub­program.
 +
 +\\ In this situation, the user must ensure argument compatibility. In particular, string vari­ables must be converted from C arrays to FORTRAN or Ada string descriptors. The actual code used in the interface routine for argument conversion will depend on the language. Examples are given below for Ada and FORTRAN. Each example assumes the subroutine is called as follows:
 +
 +\\ (dummy 3.7 "An example string"​)
 +
 +__**VMS Ada Example**__
 +
 +Note the procedure definition in line 2 of the Ada routine. The numerical value is defined as an IN OUT type and the string as an IN. Also note the compiler PRAGMA on line 4 5. PRAGMA is DEC Ada specific,​ and a similar statement will be needed for other compil­ers. Following the Ada routine is an example of a C interface function that calls the Ada sub­routine. The C routine must convert a C string into an Ada string descriptor using the **MakeStringDsc** (see section 6.7 for more on string conversion) function as shown in line 16 of the C routine. Note that the C function passes the //address// of the numerical parameters to the Ada subprogram (line 16) and a pointer to a descrip­tor for the string parameter. Note also that the **UserFunctions** definition (lines 21 24) calls the dummy C routine, not the Ada pro­gram.
 +
 +\\ package DUMMY_PKG is\\ procedure DUMMY (Value : in out float ;\\ Name : in string);\\ \\  **(The following two lines are DEC Ada specific)\\ \\ ** pragma EXPORT_PROCEDURE (DUMMY\\ PARAMETER_TYPES => (float,​string));​\\ \\ end DUMMY_PKG;​\\ \\ 
 +
 +   Ada interface to CLIPS internal functions, see Appendix A\\ with CLIPS_INTERNALS;​ use CLIPS_INTERNALS;​
 +
 +\\ PACKAGE Dummy_PKG IS\\ \\ package body DUMMY_PKG is\\ \\ procedure DUMMY (Value : in out float ;\\ Name : in string) is\\ \\ begin\\    Value and Name may be used as normal Ada variables.
 +
 +-- Name should not be modified by this procedure since
 +
 +-- it has a direct pointer to a CLIPS C string.\\ \\ end DUMMY;\\ \\ end DUMMY_PKG;
 +
 +__**C interface routine**__
 +
 +#include <​stdio.h>​\\ #include "​clips.h"​\\ \\ \\  **(The following two lines are VAX VMS specific)**\\ \\ #include <​descrip.h>​\\ struct dsc$descriptor_s *MakeStringDsc();​\\ \\ c_dummy()\\ {\\ double value;\\ char *name;\\ extern int dummy();\\ \\ value = RtnDouble(1);​\\ name = RtnLexeme(2);​\\ \\ dummy(&​value,​ MakeStringDsc(name));​\\ \\ return(0);​\\ }\\ \\ UserFunctions()\\ {\\ DefineFunction("​dummy",​ '​i',​ c_dummy, "​c_dummy"​);​\\ }
 +
 +__**VMS FORTRAN Example**__
 +
 +The VMS FORTRAN routine looks very similar to the Ada routine and, in fact, uses the same C interface function listed for VMS Ada.
 +
 +\\ subroutine dummy(value,​ name)\\ C\\ REAL value\\ CHARACTER *80 name\\ C\\ C value and name may now be used as normal FORTRAN variables\\ C\\ •\\ •\\ •\\ C\\ return\\ end
 +
 +\\ Note that the previous two examples performed the string conversion in C, not in the language (Ada or FORTRAN) to which the string was being passed. On some machines, it may be easier to convert the string in the language (Ada or FORTRAN) to which the string is being passed rather than in the language (C) from which the string is being passed.
 +
 +===== 6.7 String Conversion =====
 +
 +Much of the information that needs to be passed between CLIPS and another lan­guage typically is stored as strings. The storage of string variables can differ radically between languages. Both Ada and FOR­TRAN use a special (machine dependent) string descriptor for string data types, whereas C uses simple arrays. Because of this difference, special functions must be de­fined to convert FORTRAN or Ada strings to C strings and back. The implementation of these functions will be different for every lan­guage and computer. Typically, two functions are needed: one to convert an Ada or a FORTRAN string to a C string, and one to convert a C string to an Ada or a FORTRAN string descriptor. When converting C strings that have been provided by CLIPS to strings suitable for other languages, //do not// modify the original C string. The following table shows the string conversion routines provided in the interface packages in appendix A.
 +
 +\\ | **Environment** | **Function to Convert** **TO a C string** | **Function to Convert** **FROM a C string** |
 +| VMS Ada | ADA_TO_C_STRING | MakeStringDsc |
 +| VMS FORTRAN | CONVERT_TO_C_STRING | MakeStringDsc |
 +
 +\\ The interface package does all of the converting from Ada or FORTRAN strings to C strings. Users will have to convert from C when defining functions that are passed parameters from CLIPS. Appendix A.3 has a listing for a function that will convert C strings to Ada or FORTRAN character strings under VAX VMS.
 +
 +===== 6.8 Compiling and Linking =====
 +
 +After all routines are defined, they must be compiled and linked to execute. The man­ner of compilation will depend on the machine on which the user is working. Two examples are given below: one for VMS Ada and one for VMS FORTRAN.
 +
 +==== 6.8.1 VMS Ada Version ====
 +
 +1) Copy all of the CLIPS include files and Ada interface package to the user directory.
 +
 +\\ **$copy [**{CLIPS master directory}**]*.h [**{user directory}**]**
 +
 +**$copy [**{CLIPS master directory}**]*.ada [**{user directory}**]**
 +
 +\\ 2) Create an object file from the file holding the **UserFunctions** definition.
 +
 +\\ **$cc usrfuncs.c**
 +
 +\\ 3) Set up the Ada library and compile the Ada routine(s).
 +
 +\\ **$acs create library [**{user directory}**.adalib]**
 +
 +**$acs set library [**{user directory}**.adalib]**
 +
 +**$ada** {Ada files, including the interface packages}
 +
 +\\ 4) Export the Ada object code from the DEC ACS library.
 +
 +\\ **$acs export/​main** {Ada files, including the interface package}
 +
 +\\ 5) Define the link libraries and link all of the files together. Note that, prior to linking, each user must define the standard link libraries with the **define lnk$library** command. This usually is done once in the **login.com** file during login. This definition may be different for each VMS system.
 +
 +\\ **$link/​executable=**{exec name} {Ada files}, **usrfuncs, [**{CLIPS master di­rectory}**] clipslib/​library**
 +
 +\\ This will create an embedded version of CLIPS using an Ada routine as the main pro­gram. To create a program that uses the CLIPS interface but calls Ada subprograms,​ modify step 4 to read
 +
 +\\ **$acs export** {user'​s Ada packages}
 +
 +\\ 5) Copy the CLIPS **main.c** file from the CLIPS master directory and remove the **UserFunctions** definition from the CLIPS **main.c** routine. Then recompile
 +
 +\\ **$cc main**
 +
 +\\ 6) Link with the following command:
 +
 +\\ **$link/​executable=**{exec name} {Ada files}**,** **main, usrfuncs** **, [**{CLIPS master directory}**] clipslib/​library**
 +
 +==== 6.8.2 VMS FORTRAN Version ====
 +
 +1) Copy all of the CLIPS include files to the user directory.
 +
 +\\ **$copy [**{CLIPS master directory}**]*.h [**{user directory}**]**
 +
 +\\ 2) Create an object file from the file holding the **UserFunctions** definition.
 +
 +\\ **$cc usrfuncs.c**
 +
 +\\ 3) Compile the FORTRAN routine(s).
 +
 +\\ **$fortran** {FORTRAN files}
 +
 +\\ 4) Link all of the files together.
 +
 +\\ **$link/​executable=**{exec name} {FORTRAN files}, **usrfuncs, [**{CLIPS master directory}**] clipslib/​library,​ clipsforlib/​library**
 +
 +\\ Note that one of the FORTRAN programs //must// be a main program.
 +
 +==== 6.8.3 CLIPS Library ====
 +
 +All of the previous examples assume a CLIPS library has been created on the user's ma­chine. A CLIPS library can be made with any standard object code library pro­gram and should include all of the CLIPS object code files //except// the **main.c** file. A library also may be made for the interface packages.
 +
 +===== 6.9 Building an Interface Package =====
 +
 +To develop an interface package for CLIPS and FORTRAN, Ada, or any other lan­guage, the primary need is the string conversion routines. Once these have been developed, the rest of the interface package should look very similar to the examples shown in appendices A.1 to A.3. The majority of the conversion work should be done in the interface package. Note that if a CLIPS function takes no arguments then it is not necessary to write an interface function for it. For example, the function ListFacts takes no arguments and has no return value and can therefore be called directly (however, some languages, such as Ada, will require the function to be declared). The Ada listing in appendix A.1 use pragmas to map the C ListFacts function to the Ada xListFacts function (for consistency with the other functions which are proceeded by an x). The FORTRAN listings in appendix A include interface routines to function which do not require them as well. The functions listed in appendix A also directly mimic the equivalent C functions. That is, functions which return the integer 0 or 1 in C have the exact same value returned by their Ada and FORTRAN counterparts (rather than a boolean or logical value). It would normally be more useful to directly map these integers values into their boolean counterparts (TRUE or FALSE) in the other language.
  
 
 
clips/apg3.txt · Last modified: 2010/01/04 20:31 by admin
topheader
© 1998-2021, SciOS Scientific Operating Systems GmbH

Legal | Credits | Profile | Contact | Customer Login