The Lotus Domino for AS/400 server and Lotus Notes client have generated a lot of attention in the groupware arena over the past year and a half. As many of you have begun to leverage this investment, a question you have probably pondered is how to call existing AS/400 programs from LotusScript. One of the techniques you may have considered using to do this is to call stored procedures in SQL through the ODBC ExecProcedure method. However, although this technique works from a Domino for AS/400 server and Notes client with minimal effort, it is usually quite expensive in terms of performance. As an alternative to calling stored procedures, I have been using the external-function call capability from LotusScript on the AS/400 with much success in terms of both performance and reuse. I will describe a technique I use as a foundation that you can expand upon to suit your particular needs for calling AS/400 programs from LotusScript.
Some of you may be aware that the LotusScript language allows you to call external functions that are compiled entities that reside in their native operating system. Please keep in mind that calling external functions is possible only with scheduled agents or agents called by the WebQueryOpen and WebQueryClose events in a form design. (The server calls the agent and has access to the external function. On the Windows 32 platforms, external functions are entry points to a Dynamic Link Library (DLL). An external function can be called from LotusScript on an AS/400 if that function is an entry point to an AS/400 service program (i.e., a program of object type *SRVPGM), and, because of the way parameters are passed, the function must be written in C on the AS/400. However, you do not have to be a crackerjack C programmer to use my technique, which I will walk you through below.
Declare Your Independence
The process for calling external C functions from LotusScript is described in the Lotus help documentation. The LotusScript Declare statement is the mechanism you use to identify where the external function entry point is stored in the Service Program object on the AS/400.
The following LotusScript is a sample database agent and will be called SimpleAgent (be sure the Declare statement is placed in the Declaration event of the agent):
Declare Function as400CFunction Lib_
/qsys.lib/qgpl.lib/as400sp.srvpgm_ (Byval inparm As String, Byval_ outparm As String) As Integer
Sub Initialize
Dim inval as String
Dim outval as String
Dim rc as Integer
inval = input value
outval =
rc = as400CFunction(inval, outval)
Print inval= & inval & outval= &_ outval
End Sub
Here are some notes about what you see in this statement:
The string value /qsys.lib/qgpl.lib/as400sp.srvpgm, which follows the Lib keyword, is an exact reference to the service program as a file in the AS/400 Integrated File System (AS/400 IFS) on the AS/400. The service program is in QGPL and is named AS400SP with type *SRVPGM.
The entry point is named as400CFunction. (You will see this again in the discussion to follow.)
Two String parameters are passed to the external function: One is passed by value as input, and the other is returned by the second parameter.
Both String parameters use the Byval modifier, which makes it look as if a copy of the data is being passed; therefore, the second parameter appears as though it wont get assigned back. Trust me; data is passed back into outparm, so ignore the Byval modifier.
On the AS/400, LotusScript agents run using the ASCII character set. Luckily, the AS/400
LotusScript interpreter automatically converts from ASCII to EBCDIC before parameters are passed to and from the external function. This means that, when your service program gets control, the parameters are in EBCDIC.
C Eye to Eye
The C function definition for the external function declared will look something like this:
#include
#include
#include
int as400CFunction(char *inparm, char *outparm) {
strcpy(outparm,
running as400CFunction);
printf (inparm=%s outpart=%s , inparm, outparm);
return(0);
}
This C function needs some explanation, especially for those of you unfamilar with the C language:
The #include statements are directives that include definitions for runtime routines used in the program (namely, strcpy and printf).
The entry point is named as400CFunction, which matches the entry point name on the LotusScript Declare statement previously discussed.
Notice how the input and output parameters are defined: pointers to null terminated strings.
A return value is assigned by strcpy, and printf outputs the contents of the two strings. You will find the output in a spool file under the QNOTES user ID when you run this function.
The value returned to the LotusScript function is assigned as 0 by return (which is at the end of the function).
This C function needs to be compiled into an AS/400 service program object called AS400SP in the QGPL library. The following two AS/400 CL commands will create this service program for you:
CRTCMOD MODULE(QGPL/AS400SP) SRCFILE(QGPL/QCSRC)
SRCMBR(AS400SP) OUTPUT(*PRINT)
CRTSRVPGM SRVPGM(QGPL/AS400SP)
MODULE(QGPL/AS400SP) EXPORT(*ALL)
SimpleAgent Man
You should now be able to run SimpleAgent; the only question is how. There are essentially three ways to test SimpleAgent. One is to make SimpleAgent a scheduled agent and set the runtime at either some short duration or some specific time, but this is not the easiest way to test code. Another way to test SimpleAgent is to make it a WebQueryOpen or WebQueryClose agent for a form and open a form from a Web browser. The final
wayand the one I like to use to test agents like thisis to open SimpleAgent from a Web browser. This requires the Domino for AS/400 server to be running the HTTP task. The following URL is a sample of how to open an agent like this from a Web browser:
Http://someserver.com/adir/somedb.nsf/SimpleAgent?OpenAgent
Good News and Bad News
The technique I have described has many uses but has some catches as well. You can call a C function, for example, but calling an RPG program directly is not recommended because RPG programs are not threadsafe by default. It is also possible to write C functions that are not threadsafe. (Stay away from static global variable declarations, and you should be OK for the most part.) Thread safety is a key concern when it comes to calling native AS/400 programs from LotusScript, so be careful.
LATEST COMMENTS
MC Press Online