v5.0 / 10 of 23 / 01 sep 99 / gvg
* A VEE UserObject llows you to collect a set of objects into a high-level, user-defined object -- a subprogram. UserObjects can be nested. You can also convert UserObjects into UserFunctions that can be called from multiple places in a program, as well as be incorporated into formulas in Formula boxes.
This chapter provides a quick overview of these two VEE features.
* A VEE UserObject allows you to encapsulate functions inside a single
object. You can then "streamline" the UserObject into a UserFunction, which
becomes part of the program's invisible "background", only becoming visible
when it is invoked.
The invisibility of UserFunctions makes them harder to edit than UserObjects,
but a UserFunction has several advantages over a UserObject:
* Let's build a simple UserObject to, say, take the square root of a number,
and then convert it into a UserFunction. To get a UserObject, use the menu
entry "Device -> UserObject". This gives you:
You have now completed a UserFunction. You can add more in the same fashion.
* Once you have completed a set of UserFunctions, you can edit them or
incorporate them into programs. Suppose you have created a set of
UserFunctions with the names RootMap, LogMap, and SqrMap; you can edit any of
these UserFunctions by using the VEE Edit menu's "Edit UserFunction" entry:
This is largely intuitive, but one thing that quickly comes to mind as useful
to do is to make a copy of a UserFunction so you can modify it into a new
UserFunction. This is also a little tricky, since if you don't do it just
right you'll end up with the first UserFunction modified to the coding of the
second. The correct process is as follows:
* Anyway, once you have created a set of UserFunctions you can then delete
any Call Function objects and save the result to a file as a UserLibrary.
Suppose you have a UserLibrary named "lib1.vee". You can then use the "File"
menu's "Merge Library" (not "Merge" -- "Merge Library" ... "Merge" adds
in a separate program) to add the UserFunctions to a program you are working
on. You can add as many UserLibraries as you like in this way -- as long as
you don't try to add two UserLibraries that contain a function with the same
name (VEE doesn't like that too much).
However, this merges the UserFunctions permanently into your VEE program; you
can only get rid of them by individually deleting them. If you want to
dynamically load UserLibraries, you can use the Import Library object:
* Note that there is one subtlety with UserObjects and UserFunctions: if you
perform a loop within one and send a series of values to an output pin,
you'll only get the last value it wrote when the UserObject or UserFunction
exits.
This is because these elements really are subprograms of sorts, and of course
if you wrote a subprogram in BASIC:
Similarly, one user wrote a VEE program of the form:
* With the introduction of Win95, which provided much more robust networking
facilities than Win3, it became possible to use various networking features
with VEE 3.2 on that platform that had been previously available for VEE on
HP-UX. One of the more interesting of these features is the remote procedure
call, or RPC.
With RPCs, a VEE on one computer on a network (a "client") can execute the
functions of a UserFunction library (a "UserLibrary") on VEE on another
computer on the LAN (a "server").
The trick is to use the Import Library object on the VEE client to specify
loading a UserLibrary at the remote VEE server. The UserFunctions in the
server's UserLibrary can then be invoked by the client with Call Function
objects. The inputs to the UserFunctions are sent from the client to the
server over the network, the UserFunctions are executed on the server, and
the results are sent back to the client over the network.
VEE operates invisibly on the server. There is a special program that is
installed along with VEE called "veesm.exe" (the VEE service manager) that
has to be run beforehand to allow VEE server operation. You can either run
it manually before beginning the network session, or include it in the Win95
StartUp menu to ensure it is always running after Win95 boots.
When the VEE client sends a message to the server to import the UserLibrary,
the VEE service manager brings up VEE without displaying its user interface
and loads the UserLibrary. The client can then execute the various
UserFunctions on the server.
While by default, the VEE user interface will not appear on the server, if
one of the UserFunctions is in the form of a "Show Panel On Execute" pop-up,
the VEE user interface will be displayed when the pop-up is executed.
* Let's look at this in more detail, in the reverse order from how it was
described above. Let's build a UserLibrary with three UserFunctions, one
named "TestFn":
* Anyway, I created these three UserFunctions and stored them in a
UserLibrary named xrpctest.lib. I then ran the "veesm.exe" program and
it popped up a little window. I hid it on the Win95 TaskBar, since there was
no particular reason in this case for it to be visible.
* This done, I was ready to invoke the three UserFunctions as RPCs. I went
to another machine and wrote the following program (see xrpctest.vee for
the source):
The XWindow Display Server specifies where popups will appear (this doesn't
apply to PCs). Geometry specifies the size of the VEE user interface if it
pops up on the server, the default is OK in this case. Remote Debug allows
tracing the operation of the UserFunctions on the remote server (nice to
know, but we won't tinker with it here).
Anyway, running this program invokes the "TestFn" UserFunction invisibly and
generates results; then the "PopUp" UserFunction is invoked, and the popup
panel appears on the server with the prompt: "THIS IS A TEST". I type in:
"HI THERE" -- to the panel on the server and click on OK; the string is sent
back to the client. Finally, the "SqrFn" UserFunction takes a list of
integers and returns their squares.
The cleanliness of client-server operation is quite surprising. As long as
the networking is set up OK, it works without much trouble.
[10.1] USEROBJECTS & USERFUNCTIONS
[10.2] VEE REMOTE PROCEDURE CALLS
[10.1] USEROBJECTS & USERFUNCTIONS
+-------------------------------------------------------+
| UserObject |
+---+-----------------------------------------------+---+
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
+---+-----------------------------------------------+---+
Next select a formula box (from "Math -> Formula"), place it in the
UserObject, and put the expression "sqr(A)" into it:
+-------------------------------------------------------+
| UserObject |
+---+-----------------------------------------------+---+
| | | |
| | | |
| | +------------------------------+ | |
| | | Formula | | |
| | +-------+-----------+----------+ | |
| | | A Any |[ sqr(A) ]| [result] | | |
| | +-------+-----------+----------+ | |
| | | |
| | | |
+---+-----------------------------------------------+---+
To complete the UserObject, move the cursor over the left margin of the
object and press Ctrl+A to get an input pin, move the cursor over the right
margin and press Ctrl+A to get an output pin, and wire the Formula object to
these pins:
+-------------------------------------------------------+
| UserObject |
+---+-----------------------------------------------+---+
| | | |
| | | |
| | +------------------------------+ | |
| | | Formula | | |
| | +-------+-----------+----------+ | |
| A +------->| A Any |[ sqr(A) ]| [result] +------>| X |
| | +-------+-----------+----------+ | |
| | | |
| | | |
+---+-----------------------------------------------+---+
* To convert the UserObject into a UserFunction, click on the UserObject's
toaster box to get its menu:
+-------------------------------------------------
| UserObject
+---------------------+-------------
| Move |
| Size |
| Clone |
| Help |
+---------------------+
| Show Description |
| Breakpoint |
|*Show Title |
| Change Title... |
| Terminals >|
+---------------------+
| Make UserFunction | <---
| UnPack |
Select this and a dialog box pops up to allow you to specify the function
name. Give it a name, say "RootMap" (for "square root mapping"):
+---------------------------------+
| Make UserFunction |
+---------------------------------+
| |
| Function Name [ RootMap ] |
| |
| +--------+ +--------+ |
| | OK | | Cancel | |
| +--------+ +--------+ |
+---------------------------------+
-- and click on "OK". The UserObject disappears, to be replaced by a Call
Function object:
+-------------------------------------------+
| Call Function |
+-------+-------------------------------+---+
| A Any | Function Name [ RootMap ] | X |
+-------+-------------------------------+---+
Note that this is not the UserFunction itself. The UserFunction has
become invisible. All it does it call the UserFunction.
Edit Debug Flow Device
-+----------------------------+-
| Cut | Cuts an object or objects from program.
| Copy | Copies an object or objects.
| Paste | Inserts object or objects to program.
| Clone | Duplicates an object or objects.
+----------------------------+
| Delete Line Shift+Ctrl+LB |
| Clean Up Lines |
+----------------------------+
| Select Objects Ctrl+LB |
| Move Objects |
| Add To Panel |
+----------------------------+
| Create UserObject |
| Edit UserFunction ... |<--
+----------------------------+
Click on that entry and you'll get a list of UserFunctions currently residing
in VEE. Select one and you get a "window" into the UserFunction:
+------------------------------------------------+
| UserFunction: RootMap |
+---+----------------------------------------+---+
| | | |
| | | |
| | +------------------------------+ | |
| | | Formula | | |
| | +-------+-----------+----------+ | |
| A +--->| A Any |[ sqr(A) ]| [result] +--->| X |
| | +-------+-----------+----------+ | |
| | | |
| | | |
+---+----------------------------------------+---+
| [ Done ] |
+------------------------------------------------+
This viewport has the following menu:
+------------------------------
| UserFunction: RootMap
+---------------------+-----------------
| Move |
| Size |
| Help |
+---------------------+
| Change Properties |
| To Panel |
| To Detail |
| Show Description |
+---------------------+
| Show Panel on Exec |
| Trig Mode >|
| Terminals >|
| Edit >|
+---------------------+
| Make UserObject |
| Delete |
+---------------------+
| Done |
+---------------------+
There's only a few elements in this menu that are particularly useful to the
UserFunction view: "Change Properties" allows you to change the
UserFunction name; "Make UserObject" allows you to convert the UserFunction
back into a UserObject; and "Delete" of course deletes the UserFunction from
the system.
+------------------------------------------+
| Import Library |
+------------------------------------------+
| Library Type [ User Function ] |
| Library Name [ lib1 ] |
| File Name [ LIB1.VEE ] |
+--------------------+---------------------+
|
+-----------------+------------------+
| Call Function |
+------+ +---+----------------------------+---+ +-------+
| 2 +-->| A | Function Name [ RootMap ] | X +-->| 1.414 |
+------+ +---+-------------+--------------+---+ +-------+
|
+--------------+-------------+
| Delete Library |
+----------------------------+
| Library Name [ lib1 ] |
+----------------------------+
This little program loads the LIB1.VEE UserLibrary, executes a function out
of it, then deletes it when it is done. (The "Library Name" -- "lib1" in
this case -- is an arbitrary handle for the program to cross-reference the
library; you can make it anything you like.) You can load multiple libraries
in the same program and delete each when you please. Again, the libraries
cannot have two functions with the same name.
SUB Test( N )
INTEGER I
FOR I = 1 TO N
N = I^2
NEXT N
END SUB
-- you'll only get the last value of N^2 out of it. To return a set of
values, you have to put them in an array and return the entire array.
+-------+
| Until |
| Break +------------------------+
+---+---+ |
| +----------------+---------------+
+-------+-------+ | UserObject |
| Message Box: | +--------------------------------+
| "DONE!" | | +---------------+ +--------+ |
+---------------+ | | For Count: 10 +-->| 3 | |
| +-------+-------+ +--------+ |
| | |
| +---+---+ |
| | Break | |
| +-------+ |
+--------------------------------+
The Until Break never executed, even though there was a Break object in the
UserObject. The reason was simple: the Break object was in a separate
context and it did not apply to the outer loop.
[10.2] VEE REMOTE PROCEDURE CALLS
+--------------------------------------------------------------------+
| UserFunction: TestFn |
+---+------------------------------------------------------------+---+
| | | |
| | +----------------------------------------------------+ | |
| A +-->|[ (A>0 ? "Greater" : (A<0 ? "Less Than" : "Zip")) ] +-->| X |
| | +----------------------------------------------------+ | |
| | | |
+---+------------------------------------------------------------+---+
-- one named "PopUp:
+---------------------------------------------------------+
| UserFunction: PopUp |
+---+-------------------------------------------------+---+
| | | |
| | +----+ | |
| | | OK +---+ | |
| | +----+ | | |
| | | | |
| A +--+ +--------------+ +-------+-------+ +-->| X |
| | | | AlphaNumeric | | Text | | | |
| | | +--------------+ +---------------+ | | |
| | +-->| | | +--+ | |
| | +--------------+ +---------------+ | |
| | | |
+---+-------------------------------------------------+---+
-- and one named "SqrFn":
+-------------------------------------+
| UserFunction: SqrFn |
+---+-----------------------------+---+
| | | |
| | +---------------+ | |
| | | Formula | | |
| | +---+-----------+ | |
| +----->| A | A*A +----->| X |
| | +---+-----------+ | |
| | | |
| | | |
+---+-----------------------------+---+
"TestFn" simply checks the value of the input and identifies whether it is
lest than, equal to, or greater than by returning a string. "PopUp" creates
a pop-up panel on the server to allow display of an output prompt and return
of an input string. It has the "Show Panel On Execute" flag set and
generates a pop-up panel of the form:
+------------------------+
| |
| +--------------+ |
| | AlphaNumeric | |
| +--------------+ |
| | <prompt> | |
| +--------------+ |
| |
| +--------------+ |
| | Text | |
| +--------------+ |
| | <input text> | |
| +--------------+ |
| |
| +------+ |
| | OK | |
| +------+ |
| |
+------------------------+
"SqrFn" simply returns the squared contents of a scalar or array.
+-------------------------------------------------+
| Import Library |
+-------------------------------------------------+
| Library Type [ Remote Function ] |
| Library Name [ tl ] |
| Host Name [ hplvcoyote ] |
| Remote File Name [c:/vlib/xrpctest.lib] |
| Remote Timeout [ 60 ] |
| XWindow Display Server [ ] |
| geometry (800x500+0-0) [ ] |
| Remote Debug [ ] |
+------------------------+------------------------+
|
+-----------+----------+
| Call tl.TestFn |
+-----+ +----------------------+ +-------+
| 0 +-->|[ tl.TestFn +-->| Zip |
+-----+ +-----------+----------+ +-------+
|
+-----------+----------+
| Call tl.PopUp |
+----------------+ +----------------------+ +------------+
| THIS IS A TEST +-->|[ tl.PopUp +-->| HI THERE |
+----------------+ +-----------+----------+ +------------+
|
+-------------+ | +--------------+
| Integer | | | Alphanumeric |
+-------------+ +-----------+----------+ +--------------+
| 0000: 3 | | Call tl.SqrFn | | 0: 9 |
| 0001: 5 | +----------------------+ | 1: 25 |
| 0002: 9 +-->|[ tl.SqrFn +-->| 2: 81 |
| 0003: 25 | +-----------+----------+ | 3: 625 |
| 0004: 13 | | | 4: 169 |
+-------------+ | +--------------+
|
+-------------+------------+
| Delete Library |
+-------------+------------+
| Library Name [ tl ] |
+--------------------------+
The key to this program is the settings in the Import Library box:
+-------------------------------------------------+
| Import Library |
+-------------------------------------------------+
| Library Type [ Remote Function ] |
| Library Name [ tl ] |
| Host Name [ hplvcoyote ] |
| Remote File Name [c:/vlib/xrpctest.lib] |
| Remote Timeout [ 60 ] |
| XWindow Display Server [ ] |
| geometry (800x500+0-0) [ ] |
| Remote Debug [ ] |
+-------------------------------------------------+
Setting the "Remote Function" option gives the appropriate following fields
You then can specify a library name ("tl" in this case -- it's quite
arbitrary, all it does is give a handle for the rest of the program to use),
the name of the server computer ("hplvcoyote" in this case), the name of the
UserLibrary on the server computer ("c:/vlib/xrpctest.vee"), and a timeout
for the network interaction. (Note that you use "/" in describing the
path, not "\" -- the Import Library box won't swallow "\" -- but it
works OK.)