Method for extending a fourth generation programming language5721929Abstract A system for extending the capabilities of a programming language, particularly a 4GL, wherein an extension of the programming language is created as a class within the C++ programming language. The extension class must also include code to register the extension class with the programming language, so that the programming language execution engine can call the functions of the class. When the extension function receives control, it receives any parameters defined within the programming language statement that called the extension function, and it can return a value to the programming language. The extension function may call other functions of the programming language, and it may call any other types of functions, therefore, the extension function has complete control over its domain and scope. Claims What is claimed is: Description FIELD OF THE INVENTION
______________________________________
class NewCustomClass : public External
private:
//
// User defined private data and function members
//
protected:
//
// User defined protected data and function members
//
public:
NewCustomClass (EngineContext &ec) : External (ec){ }
Value *Execute (int expectingReturn);
//
// User defined public data and function members
//
};
Value* NewCustomClass:: Execute (int expecting Return)
{
/
// User defined processing such as a new algorithm,
// interface to user's business application or
// interface to third party appliaation
//
if (expectingReturn)
{
if (error)
return (CreateValue (0L));
else
return (CreateValue (1L));
}
else
return 0;
}
______________________________________
wherein the underlined class and variable names would be changed for each specific class being created. In addition to the template for C++ extensions, the invention includes methods which give the user complete control over the input to and output from an extension. The input is popped from a conventional stack and output is pushed onto a conventional stack. The Value class is used to input and output data, although those skilled in the art will recognize that any arbitrary data type could be used for input and output of data. The value class supports returning basic types, such as integer, long, double, char, char *, and complex types such as an array. The first example shown below defines how a file name would be input to an extension expecting a single argument representing a file name. The user can test the stack to verify that the argument was passed by the caller. In this example, one argument is expected, so a test of greater than or equal to 1 is used. The user implementing the extension defines the number of arguments and defines the method for verifying that all arguments are supplied by the caller.
______________________________________
if (parmStack->Test( ) >= 1)
Value *fileName = parmStack->Pop( );
______________________________________
The next example shown below defines how an extension would return data in the argument list, thus allowing the extension to return an arbitrary amount of data. For example, a function "findFile" is implemented by a C++ extension "FindFileClass". The syntax for using this extension is "error=findFile (criteria, filename)" where the caller defined criteria for finding a file is stored in "criteria", the file name matching the criteria is returned in "fileName" and "error" is equal to one for success and is equal to zero if a failure occurs. Therefore, the functions pops the arguments off the stack and assigns the file name found to the appropriate argument.
______________________________________
Value *criteria = parmStack->Pop( );
Value *fileName = parmStack->Pop( );
*fileName = (const char*) fileNameMatched;
______________________________________
The next example shown below defines how an extension would execute a function of the programming language from within the C++ extension and pass arguments to the programming language function. For example, a programming language function "openFile" is implemented by a C++ extension "OpenFileClass". The syntax is "error=openFile (fileName)" where the caller supplied file name is the file to be opened and "error" will be set to one for success and set to zero for failure. First, the extension function gets a handle to an instance of the programming language function to be executed. This handle is of type "Module *" and the name of the function is used to get the handle. Second, the handle is used to create a parameter stack and the argument list is pushed onto the stack. Last, the handle is used to execute the function. All programming language functions implemented as a C++ extension have an "Execute" member, so this member is used to perform the function.
______________________________________
Module *openFile = engineContext.GetModule ("openFile");
openFile ->parmStack = new ParameterStack;
openFile ->parmStack-> Push (fileName);
Value *returnValue = openFile ->Execute ( );
______________________________________
Last, a C++ extension is made accessible from within the programming language by registering the extension with the transaction engine of the language. The transaction engine is that part of the programming language that executes programming language statements and a component defines the domain for the functions within the component. Extensions are registered by the transaction engine from within a C++ file called "extend.cc". This file contains a function prototype to execute containing source code to register extensions for a particular component and a function "intializeExtensions" which executes the prototype. The example shown below indicates the code previously defined and the code added to register functions for a new component.
______________________________________
//
// Prototypes for previously defined components
//
void initializeNewComponent (EngineContext &);
void initializeExtensions (EngineContext &ec)
//
// Execution for previously defined components
//
initializeNewComponent (ec);
}
______________________________________
The definition of the prototype function is located in component's source code. All functions in the component which are accessible from the programming language are registered from within the function "initializeNewComponent". The next example show below defines the prototype function mentioned above and registers two extensions used in previous examples.
______________________________________
void initializeNewComponent (EngineContext &ec)
(new FindFileClass (ec))->Register ("findFile");
(new OpenFileClass (ec))->Register ("openFile");
}
______________________________________
FIG. 1 shows a block diagram of a computer system incorporating the present invention. Referring now to FIG. 1, a computer system 100 contains a processing element 102 that communicates with other elements of the computer system 100 over a system bus 104. A keyboard 106 and a mouse device 110 allow input to the computer system 100 while a graphics display 108 allows software within the computer system 100 to output information to a user of the system. A disk 112 stores the data and processes of the present invention. A memory 116 contains an operating system 118, which is typically the Unix Operating System, although any other operating system will work in a similar manner with the invention. The program language extension of the present invention is embodied within a transaction engine 120, a program 122, and program extensions 124. FIGS. 2A and 2B show an example of an extension used with the present invention. Referring now to FIGS. 2A and 2B, step 1 shows that the extension must include a header file named "external.h", because the extension class must be derived from a class called External and the definition for the External class is in the header file external.h. In the example of FIG. 2A, the extension also includes a header file named "math.h", however, this file is specific to the particular code within the extension example and would not be needed in other extensions. Step 2 shows that the extension must be created as a C++ class which is derived from the External class. This is necessary in order to inherit the characteristics of the External class, in particular the register function which must be called to identify the extension class to the programming language. Step 3 shows that the extension must define a constructor method in order to pass the engine context to the base class, the External class. The engine context is a set of data used by the programming language in interpreting the statements of the programming language. All interpreted programming languages have an equivalent to the engine context. Step 4 shows that the extension must define a public function having the name "Execute", and this function must have a type of "Value *". Those skilled in the art will recognize that any type could be used, and that the type "Value *" is specific to this particular implementation. The Execute member should include one argument of type "int", and this argument indicates whether the caller of the function is expecting a return value. The value for this parameter would typically be one if the caller is expecting a return and zero is the caller is not, although those skilled in the art will recognize that this parameter could be set to any value so long as the caller and the creator of the extension each understand the meaning of the value. Step 5, shown in FIG. 2B, shows that the return value should be returned as a pointer to an instance of the value class, in this particular example. Steps 1 through 5 are an example of the code that would be included in the actual extension. Step 6 shows code that is placed into a file named "extend.cc", and this code causes the functions within the class to be registered, so that they can be called from a program statement within the programming language. Step 7 shows an example of calling the extension function from within the programming language. As step 7 shows, the call to the extension function is done in a conventional manner, and requires no unusual adaptations because of the function being an extension function. FIG. 3 shows a flowchart of the process for creating an extension. Referring now to FIG. 3, block 302 shows that to create an extension the user must copy the external header file into the extension. Block 304 shows that the extension must be defined as a subclass of the External class, and block 306 shows that the extension must define an Execute member function. Once all this is accomplished, block 308 shows that the external function must be compiled and block 310 shows that the registration code must be placed in the "extend.cc" file. Block 312 compiles the "extend.cc" file, and block 314 links the external class, with the extension class and the extend.cc file, along with the transaction engine. Once this is done, the extension is usable from within the language. FIG. 4 shows a flowchart of a portion of the transaction engine of the present invention and how this portion performs the function within an extension. The "transaction engine" is that part of the programming language interpreter that reads programming statements, determines what these statements do, and performs the function intended by the statement. That is, the transaction engine performs the interpretation within an interpreted programming language. Thus, the transaction engine is the part of the programming language that must also determine that the function being called is an extension, set up all the necessary information for the extension and call the extension so that the extension can perform the intended operation. Thus, the transaction engine is the main interpreter for the programming language as well as the extensions of the present invention. Referring now to FIG. 4, after entry, block 402 gets the next program statement from within the user program. Block 404 then determines whether the statement is a function call, and if not, block 404 transfers to block 406 which performs whatever requested operation is in the programming statement. After completing the operation, control returns to the caller of this portion of the transaction engine. If block 404 determines that the program statement is a function call, block 404 transfers to block 412 which places, on a stack, any parameters defined in the programming language statement for the function call. Block 414 then determines whether the function is a known function within the programming language. That is, is the function a part of the existing programming language. If the function is known within the language, block 414 transfers to block 408 which calls the Execute member function to perform the operation of the function. After the function returns, block 410 cleans up the stack to insure that nothing is left on the stack before returning to the caller of the engine. If the function is not part of the language, block 414 transfers to block 416 which determines whether the function is part of a registered extension. If the function name has been registered, block 416 transfers to block 408 which calls the Execute member function and then block 410 cleans up the stack before returning to the caller. If the function is not a registered function, block 416 transfers to block 418 which writes an error message indicating that an attempt was made to call an unknown function. FIG. 5 shows a flowchart of the operation of an extension within the present invention. Referring to FIG. 5, after entry, block 502 checks the parameter stack to make sure that the number of parameters passed is the number needed by the extension. If the number is incorrect, block 502 transfers to block 516 which displays an error message before returning to the transaction engine. If the number of parameters is correct, block 502 transfers to block 504 which retrieves the needed parameters from the stack and then block 506 determines whether the extension will perform a function that is a part of the programming language. That is, the extension is allowed to call functions that are built into the programming language, as part of the operation of the extension. If the extension does need to call a programming language function, block 506 transfers to block 518 which calls the transaction engine to get a "handle" of the language function. A "handle" is some form of pointer to the language function. This pointer may be an actual address of the function, or it may be an integer which represents the particular function needed, or it may be some other form. After obtaining the handle, block 520 creates a new parameter stack and then block 522 pushes parameters, for the programming language function being called, onto the stack. Block 524 then calls the Execute member of the programming language function in the same way that the transaction engine calls the Execute member of an extension. After the programming language function is complete, or if no programming language functions are needed by the extension, control goes to block 508 which performs any other desired operations within the extension. These operations can include calling any other programs defined within the extension, or programs or functions purchased from third party vendors. In this manner, the programming extensions allow the use of third party software, which typically is not usable by other fourth generation programming languages. Block 510 then determines whether a return value is required and if not, transfers to block 526 which simply returns the value zero. If a return value was required, block 510 goes to block 512 which creates a Value class object to return the data and then block 514 returns the object created in block 512. Having thus described a presently preferred embodiment of the present invention, it will be understood by those skilled in the art that many changes in construction and circuitry and widely differing embodiments and applications of the invention will suggest themselves without departing from the scope of the present invention as defined in the claims. The disclosures and the description herein are intended to be illustrative and are not in any sense limiting of the invention, defined in scope by the following claims.
|
Same subclass Same class Consider this |
||||||||||
