All Manuals > Developing Component Software with CORBA® > Appendix A: Common Lisp IDL Binding

A.6 The mapping of IDL into Common Lisp servants

This section discusses how implementations create and register objects with the ORB run time system.

A.6.1 Mapping of native types

Specifically, the native type PortableServer::Servant is mapped to the Lisp class named PortableServer:ServantBase. The native type PortableServer::ServantLocator::Cookie can take any Lisp value.

A.6.2 Implementation objects

An interface corresponding to a class named by a Lisp symbol s with package p and name n may be implemented by extending the class named by the symbol whose package is p and whose name is the concatenation of n to the string "-SERVANT".

If the interface has no base interfaces, then the associated skeleton class has as direct superclasses the class corresponding to the class named portableserver:ServantBase.

Otherwise, if the interface has base interfaces named A, B, C, and so forth, then its associated servant class has as direct superclasses the class corresponding to the servant classes corresponding to A, B, C, and so forth.

Attributes in an interface generate slots of the corresponding name in the OP package, together with server-side accessor methods.

A.6.3 Defining methods

The only portable way to implement an operation on a servant class is to use the corba:define-method macro. The syntax of corba:define-method is intended to follow the syntax of the Lisp cl:defmethod macro as closely as possible.

The syntax of corba:define-method is as follows:

corba:define-method function-name {method-qualifier}* lambda-list
   form*
function-name::= {operation-name | (setf operation-name)}
operation-name:: symbol
method-qualifier::={:before | :after | :around}
corba-specialized-lambda-list ::= setf-lambda-list 
                                  | normal-lambda-list
setf-lambda-list ::= (argument-specifier receiver-specifier)
normal-lambda-list ::= (receiver-specifier {parameter-specifier}* context-identifier)
context-identifier ::= symbol
receiver-specifier ::= (receiver-name receiver-class)
receiver-name ::= symbol
receiver-class ::= symbol
parameter-specifier ::= symbol

This corba:define-method macro is used to implement an operation on an interface. operation-name is a symbol whose name is the name either of an operation or of an attribute declared in an IDL interface implemented by the class named by the symbol receiver-class.

The number of parameter-specifiers listed in the normal-lambda-list must equal the combined number of in and inout parameters declared in the signature of the operation denoted by the function-name, or 0 if the operation is an attribute. If the function-name is a list whose car is setf, the corresponding operation-name should name an attribute that is not readonly.

If function-name denotes an operation, then the effect of
corba:define-method is to inform the ORB that requests for the operation on instances of the class receiver-class should return the value or values returned by the body forms of the define-method macro, executed in a new lexical environment in which each parameter-specifier is bound to the actual parameters and in which the context-identifier is bound to the value of the corresponding context.

The operation of corba:define-method in the case in which function-name names an attribute is analogous. The behavior of auxiliary specifiers and of dispatch is the same as their corresponding action under defmethod. Attribute accessors will be generated automatically and inherited by subclasses of the servant classes; the methods can be overridden by user definitions.

Note that the syntax of corba:define-method is a strict subset of that of defmethod: every legal corba:define-method invocation is also a legal defmethod invocation. The main difference between them is that corba:define-method only allows specialization on the first argument. An implementation is free to extend the syntax of corba:define-method, for example, to allow type-checking, interlocking, or multiple dispatch.

A.6.3.1 Example: A Named Grid

The first example shows how one might encapsulate a named grid, which is a grid of strings.

This is the IDL of the interface to a named grid of strings:

module example{
  interface named_grid{
    readonly attribute string name;
    string get_value ( in unsigned short row,
        in unsigned short column);
    void set_value ( in unsigned short row,
        in unsigned short column,
        in string value);
  }
}

The IDL compiler might generate a class corresponding to the example::named_grid interface using code something like this:

(defpackage :example)
(defclass example:named_grid(corba:object)())
A.6.3.2 Example: A Servant Class

In order to implement the IDL interface in the previous example, the user would extend the class example:named_grid-servant.

;; Sample implementation of named_grid
(defclass grid-implementation (example:named_grid-servant)
  ((grid :initarg :grid
        :initform (make-array '(2 3) :initial-element "Init")))

The attribute in the IDL will cause the class to have a slot op:name with the appropriate accessors specializing on the class.

A.6.3.3 Implementation of the IDL operations

The corba:define-method macro is used to define the methods that implement each of the operations defined in the IDL interface. These implementations do not perform any of the argument or range checking that a production system would, of course, perform.

The implementation is free to define other methods on the class, including print-object methods and auxiliary methods for initialize-instance.

(corba:define-method get_value ((the-grid grid-implementation)
                                row column)
  (aref (slot-value the-grid 'grid) row column))
 
(corba:define-method set_value ((the-grid grid-implementation)
                                row column value))
  (setf (aref the-grid row column) value))

Developing Component Software with CORBA® - 01 Dec 2021 19:38:37