Getting Started Documentation Glish Learn More Programming Contact Us
Version 1.9 Build 1556
News FAQ
Search Home


next up previous contents home.gif
Next: Testing Your Application Up: How to Write an AIPS++ Application Previous: Creating Distributed Objects

Subsections



Binding Distributed Objects to Glish

Next we show the Glish code necessary to bind this class so that the user can manipulate it directly.6

if (! is_defined('squarer_g_included')) {                       #  1
    squarer_g_included := 'yes';

include "servers.g"                                             #  2

const squarer := function(host='', forcenewserver = F) {        #  3
    self := [=]                                                 #  4
    public := [=]                                               #  5

    self.agent := defaultservers.activate("dsquarer", host,     #  6
                                        forcenewserver)

    self.id := defaultservers.create(self.agent, "squarer")     #  7

    self.squareRec := [_method="square",                        #  8
                       _sequence=self.id._sequence]
    public.square := function(x) {                              #  9
        wider self                                              # 10
        self.squareRec["x"] := x                                # 11
        return defaultservers.run(self.agent, self.squareRec)   # 12
    }

    return public

}  # constructor
}  # include guard

Some comments on individual lines:

1.
This is how you implement an include guard in Glish, to prevent multiple-inclusion of the file.
2.
This file must be included -- it contains the code that knows how to communicate with the server executables and DO's.
3.
This global function is the glish equivalent of our default constructor -- and it will end up calling the default constructor. Normally the system will keep all the objects in the same server process, however you can force new server processes (possibly on different hosts on the network) if the user wants to to use coarse-grained parallelism. Constructor functions, like most global functions and objects, should be const to prevent users from accidentally overwriting them. We shall see later how to bind classes with non-default constructors.
4.
This record will hold our private data.
5.
This record will hold our public member functions. It is the users interface to the DO.
6.
This activates a server process if necessary. dsquarer7 is the name of the binary executable on disk (it must be in the path). This is the line that maps the name of the class to the name of the executable that serves it. defaultservers implements the communication link to the server and its DO's.
7.
This line creates the DO in the server of the specified type. In the event of an error, a Glish fail will be returned.
8.
While you could create the record that is passed back and forth to the DO afresh each time, it is most efficient to cache it so it is created only once. You must always set the method name and sequence number. Note the leading underscores!
9.
This is the square() member function proxy that will invoke the real function in the DO.
10.
This is a bit of Glish magic that you need to get at your private data. If you want access to the other member functions in this function you would also need wider public.
11.
Put the supplied parameters into the record that will be passed to the DO.
12.
Invoke the actual function in the DO. Note that if you had Out or InOut parameters, the glish arguments would be of type ref, and you would have to change the arguments before returning. For example, suppose ``a'' was changed in place, then this function would look like:
            public.square := function(ref x) {
                wider self
                self.squareRec["x"] := x
                returnval := defaultservers.run(self.agent, self.squareRec)
                val x := self.squareRec.x
                return returnval
            }


Binding objects with non-standard constructors

If you are only using the default constructor, you can ignore this section.

If you have a DO class with more than one constructor, you need to have more than one global function that constructs the object. To do this, you:

1.
Factor out the code that sets up the public functions into a global function unintended for general consumption; and
2.
Call that function from each constructor function.
This is illustrated in the next code fragment. To hide the common creation function, we suggest that there names begin with an underscore and that they not be documented in user documentation.

const _define_image := function(ref agent, id) {
    self := [=]
    public := [=]

    self.agent := ref agent;
    self.id := id;

    ... Define the functions here ...
    return public
} # _define_image()

const image := function(filename, host='', forcenewserver=F) {
    agent := defaultservers.activate("image", host, forcenewserver)
    id := defaultservers.create(agent, "image", "image",
                        [theimage=filename]);

    return _define_image(agent,id);

} # image()

const fits2image := function(imagefile, fitsfile, whichhdu=1,
                             host='', forcenewserver=F) {
    ... create using the fits2image constructor ...
} # fits2image()


next up previous contents home.gif
Next: Testing Your Application Up: How to Write an AIPS++ Application Previous: Creating Distributed Objects   Contents
Please send questions or comments about AIPS++ to aips2-request@nrao.edu.
Copyright © 1995-2000 Associated Universities Inc., Washington, D.C.

Return to AIPS++ Home Page
2006-10-15