In order to simplify the process of calling an ACUCOBOL-GT program from other programming languages, the ACUCOBOL-GT 32-bit Windows runtime is encapsulated in a dynamic linked library (DLL) file. This DLL file has been further encapsulated in an Object Linking and Embedding (OLE) Automation Server.
When a program written in another language calls an ACUCOBOL-GT program, the data is passed as a pointer to a Variant type for each parameter. The ACUCOBOL-GT program receives a handle for each parameter and uses a library routine to convert the data to COBOL types. When ACUCOBOL-GT data items are passed back to this program, they pass through another library routine that converts the data back into Variant types. These library routines, W$GETVARIANT and W$SETVARIANT, are detailed in Appendix I, ACUCOBOL-GT Library Routines.
There are two methods of calling the runtime:
1. Using the runtime DLL in an OLE Automation Server, or
2. Using the runtime DLL directly, with special declarations added to the source program.
The advantage of using the Automation Server is that you can treat the ACUCOBOL-GT system as an OLE object. You do not need to insert declarations into the source code in the other programming language, you can operate in a multi-threaded environment, and the development environment is more intuitive. Using the ACUCOBOL-GT Runtime DLL, instead of the Automation Server, provides slightly improved performance and makes application distribution smaller and installation easier. However, the DLL can be called only from a single thread of execution. For example, if you call a COBOL program from a user interface control's event procedure, and the event procedure is called again before the COBOL program returns, you must detect this case and either wait or inform the user of the error.
The parameters of the Automation methods, or exported DLL functions, are all null-terminated strings, integers or Variant type variables. In some programming languages, such as Visual Basic, the Variant type is used by default for any variables that have not been assigned a data type. Since the Variant type is used to represent many different types of data, you generally don't have to convert these types of data when they are assigned to a Variant variable. The programming language automatically performs any necessary conversion. Because the ACUCOBOL-GT Automation Server and Runtime DLL routines take Variant type parameters, it easy to receive variables from, or return variables to, other languages.
NOTE: All the examples in this section use Visual Basic as the source language for code samples. Microsoft conventions for object description language are used for the descriptions of method usage.
Using the Automation Server
To use the ACUCOBOL-GT Automation Server with other programming languages:
1. Register the ACUCOBOL-GT Automation Server. Registration occurs automatically when you load the ACUCOBOL-GT runtime using the setup program that comes with the software.
When you distribute your application, if you are not using the ACUCOBOL-GT setup program, you will have to install and register the automation server on each user's machine. If you are using it as a remote server, you must install and register the ACUCOBOL-GT Runtime with the Automation Server option on the server machine. Register the ACUCOBOL-GT Automation Server by running it with no command line options or with the "/RegServer" option. This command line option is not case sensitive.
The ACUCOBOL-GT Automation Server executable is in the ACUCOBOL-GT bin directory after installation. This file is named "AcuGT.exe". The ACUCOBOL-GT Automation Server requires the same files as the ACUCOBOL-GT runtime, except for "wrun32.exe". Two additional files, "AcuGT.exe" and "AcuGT.tlb", must be installed on the machine in a single directory. For the Automation Server to work, the runtime DLL "wrun32.dll" must either be in the same directory as "AcuGT.exe" or somewhere else in the Windows DLL search path. If you move "AcuGT.exe" to a different directory, you must register it again from the new location.
Note: If you ever need to unregister the ACUCOBOL-GT Automation Server, run "AcuGT /UnregServer".
2. Start the other programming language's development environment and add "ACUCOBOL-GT Library 4.3" to your project references.
3. Add code to declare and create the AcuGT object. For example, in Visual Basic you could enter:
Dim cblObj As Object
Set cblObj = New AcuGT
Then you can control the ACUCOBOL-GT Automation Server using the Initialize, Call, Cancel and Shutown methods described below. For example, from Visual Basic you would enter:
cblObj.Initialize "-d" ' Start ACUCOBOL-GT in debug mode retVal = cblObj.Call(programName, arg0, arg1, arg2) cblObj.Shutdown
or use the "With" construct. For example:
With cblObj .Initialize "-e @myserver:\myprogs\errorfile" .Call "*myserver:\myprogs\program1.acu", "call1", 1.2, 37 .Call "*myserver:\myprogs\program1.acu", "call2", 2.3, 38 .Call "*myserver:\myprogs\program1.acu", "call3", 3.4, 39 .Cancel "*myserver:\myprogs\program1.acu" End With
If you don't explicitly call "Initialize", the Automation Server will call it for you, passing an empty command line parameter. Likewise, if you don't explicitly call "Shutdown", the Automation Server will call it for you when the object is destroyed.
In this example, after the AcuGT object is created in Visual Basic, "Initialize" is called automatically. Then, when the AcuGT object is destroyed at the end of the subroutine, the "Shutdown" method is called automatically:
Private Sub Command1_Click() Dim cblObj As Object Set cblObj = New AcuGT cblObj.Call "program" End Sub
If you have several COBOL calls to make, it is much more efficient to create the AcuGT object as a Public variable in the module, class, or form initialization. For example, this may be done using the Visual Basic CreateObject function:
Dim cblObj As Object Set cblObj = CreateObject("AcuGT.Application");
The Visual Basic CreateObject function takes an optional second parameter. This is the name of the network server where the object is created. For example, if you want to run the COBOL program on a remote machine named MOOSE, use the following syntax:
Set cblObj = CreateObject("AcuGT.Application", "MOOSE");
The Automation Server sets the "current directory" for COBOL programs to the directory containing AcuGT.exe. This allows you to use relative directory paths when you specify file names. For example, suppose you have installed the Automation server in C:\AUTOSRV\BIN, the COBOL programs and configuration files you want to use in C:\AUTOSRV\PROGRAMS and the data files in C:\AUTOSRV\DATA. You could then call the Initialize method with "-c ..\PROGRAMS\CONFIG", set CODE-PREFIX to "..\PROGRAMS" and set FILE-PREFIX to "..\DATA".
The ACUCOBOL-GT Automation Server is thread-safe, meaning that you are able to run COBOL programs asynchronously. To do this you must create a new thread and a new AcuGT object in that thread. Then you call the COBOL program from that thread.
For an example of how to create new threads in Visual Basic, see "Creating a Multithreaded Test Application" in the Visual Basic documentation. It is located in MSDN Library Visual Studio 6.0 at:
Visual BasicDocumentation/Using Visual Basic/Component Tools Guide/Creating ActiveX Components/Building Code Components/Scalability and Multithreading/Creating a Multithreaded Test Application.
It is a good idea to trap errors and handle them with your own Visual Basic error handler. For example:
On Error GoTo ErrHandler cblObj.Call "program" Exit SubErrHandler: myval = MsgBox(Err.Description, vbOKOnly, "Call not successful") End Sub
The ACUCOBOL-GT Automation Server object has the following methods.
INITIALIZE
Initializes the ACUCOBOL-GT runtime.
Usage:
HRESULT Initialize([in] VARIANT *cmdLine)
Return Value:
"Initialize" returns one of the following result codes (Note that these values are given in hexadecimal format):
Name Value Description S_OK 0 Call succeeded ACUGT_E_UNEXPECTED 80040200 Unexpected error ACUGT_E_INITIALIZE 80040201 OLE initialization failed. Make sure that the OLE libraries are the correct version.
SHUTDOWN
Shuts down the runtime.
Usage:
void Shutdown(void)
CALL
Calls the runtime.
Usage:
HRESULT Call([in] VARIANT *name, [in, out, optional] VARIANT *arg0, [in, out, optional] VARIANT *arg1, [in, out, optional] VARIANT *arg2, [in, out, optional] VARIANT *arg3, [in, out, optional] VARIANT *arg4, [in, out, optional] VARIANT *arg5, [in, out, optional] VARIANT *arg6, [in, out, optional] VARIANT *arg7, [in, out, optional] VARIANT *arg8, [in, out, optional] VARIANT *arg9, [in, out, optional] VARIANT *arg10, [in, out, optional] VARIANT *arg11, [in, out, optional] VARIANT *arg12 [in, out, optional] VARIANT *arg13 )
Return Value:
"Call" returns one of the following result codes (Note that these values are given in hexadecimal format):
Name Value Description S_OK 0 Call succeeded ACUGT_E_UNEXPECTED 80040200 Unexpected error ACUGT_E_MULTIPLE_THREADS 80040203 AcuCall has been called in multiple threads (See "Calling the Runtime DLL) ACUGT_E_INITIALIZE_FAILED 80040204 AcuInitialize failed. (AcuInitialize can not be called after AcuShutdown in a single process.) (See "Calling the Runtime DLL) ACUGT_E_PROGRAM_MISSING 80040205 Program missing or inaccessible ACUGT_E_NOT_COBOL 80040206 Not a COBOL program ACUGT_E_CORRUPTED 80040207 Corrupted program ACUGT_E_INADEQUATE_MEMORY 80040208 Inadequate memory available ACUGT_E_UNSUPPORTED 80040209 Unsupported version of object code ACUGT_E_PROGRAM_IN_USE 8004020A Program already in use ACUGT_E_TOO_MANY 8004020B Too many external segments ACUGT_E_CONNECTION_REFUSED 8004020C Connection refused - perhaps AcuConnect is not running
CANCEL
Cancels a COBOL program.
Usage:
void Cancel([in] VARIANT *program )
Calling the Runtime DLL
In order to call the ACUCOBOL-GT Runtime DLL from another programming language, you must add certain declarations to the source program. This example shows what you would use in Visual Basic:
Declare Function AcuInitialize Lib "wrun32.dll" _ (Optional ByVal cmdLine As String) As Integer Declare Sub AcuShutdown Lib "wrun32.dll" () Declare Function AcuCall Lib "wrun32.dll" _ (ByVal name As String, _ Optional param1, _ Optional param2, _ Optional param3, _ Optional param4, _ Optional param5, _ Optional param6, _ Optional param7, _ Optional param8, _ Optional param9, _ Optional param10, _ Optional param11, _ Optional param12, _ Optional param13, _ Optional param14) As Integer Declare Function AcuGetCallError Lib "wrun32.dll" () As Integer Declare Sub AcuCancel Lib "wrun32.dll" (ByVal name As String)
Then you must initialize the runtime, call the COBOL program(s) passing the program name and parameters, and shut down when you are finished. For example, in Visual Basic you would perform the following steps:
1. Call AcuInitialize to pass the runtime's command line options. For example:
returnValue = AcuInitialize("-c myconfig -le myerrors")
AcuInitialize returns a value of "0" on success and "-1" on failure. It is safe to call AcuInitialize multiple times. The command line from the first call is used and is ignored on subsequent calls.
You may use the runtime "-d" option to debug your ACUCOBOL-GT program. Specify "-d" in the command line to AcuInitialize, and the debugger window will appear when you actually call a COBOL program.
2. Then call AcuCall, passing the program name and parameters. For example, to call the program VB-TEST you would enter:
returnValue = AcuCall("vbtest.acu", testNum, testStr, testLongNum, testFloat)
AcuCall returns "0" on success and "-1" on failure. If AcuInitialize hasn't been called yet, AcuCall will call it, passing an empty command line. If AcuCall returns "-1", you may call AcuGetCallError to get the error code. The error codes are as follows:
-4 AcuCall has been called in multiple threads
-3 AcuInitialize failed. (AcuInitialize cannot be called after AcuShutdown in a single process.)
1 Program missing or inaccessible
2 Not a COBOL program
3 Corrupted program
4 Inadequate memory available
5 Unsupported version of object code
6 Program already in use
7 Too many external segments
25 Connection refused - perhaps AcuConnect is not running
3. Call AcuShutdown after you are completely finished using COBOL in your Visual Basic application.
Note that if a COBOL program issues a STOP RUN, AcuCall will return, the runtime environment will be initialized, and the calling process will continue running. This is so that STOP RUN will not shut down the calling application or development environment you are using.
4. To cancel a COBOL program, call AcuCancel passing the name of the program. For example:
AcuCancel("vbtest.acu")