Calling PL/I from Other Languages

To enable the calling of PL/I subroutines from another language, you must first initialize the PL/I run-time system (RTS), and then terminate it after the subroutine is executed. You can use either static or dynamic calls.

RTS Initialization and Termination

To drive PL/I application logic in a subroutine, use the PL/I API to initialize and then terminate the PL/I RTS exactly one time each using:

  • _lpi_init() to initialize
  • _lpi_fini_and_return() to terminate

You can implement the required initialization and termination in various ways depending on your programming needs. The following list provides some possibilities:

Call PL/I subroutines one at a time
Before each PL/I subroutine invocation you can call __lpi_init(), and after it returns, call __lpi_fini_and_return(). While this is an easy solution when you are only calling a couple of PL/I subroutines, we do not recommend it for calling a large number of subroutines as the code modifications and resulting overhead might become onerous.
Call subroutines from a COBOL program
We recommend this method as the cleanest approach for everything but CICS based applications.*

Compile your main COBOL program with the -initcall directive. In the named initcall routine:

  1. Initialize the PL/I run-time system.
  2. Register a COBOL exit procedure.
  3. Terminate the PL/I RTS from the exit procedure.
Call DLLMAIN (Windows) or fini/init mechanism (Linux/UNIX)
Enterprise Developer Open PL/I provides two initialization routines on Linux/UNIX – dllmain_cob.o and dllmain.o.
dllmain_cob.o
Use this routine when using the cob command to link your PL/I shared objects.
dllmain.o
Use this routine when linking with ldpli. See Examples: Commands to Link a PL/I Subroutine with Self-initializing RTS for an example of a Windows DLL Main().

The following applies to both routines:

  • Automatically initialize the PL/I RTS when the shared object is loaded (dynamic call).
  • Automatically de-initializes the PL/I RTS when the shared object is unloaded.
  • When a single application invokes multiple PL/I shared objects, the routine initializes the RTS once and terminates once; however, be advised that if any one PL/I object is unloaded by the application(s), this terminates the PL/I RTS prematurely. This can cause problems that are difficult to identify and resolve.

In all cases, put some thought into the overall design of your PL/I subroutines and how they are used in your program(s). Ensure that the PL/I RTS is not terminated until you are done doing PL/I work. We recommend that you initialize the PL/I RTS by first calling a single routine, and let the tear down of the COBOL environment terminate the RTS and de-initialize the environment.

* The one exception to this method applies when calling a PL/I subroutine from multiple CICS link levels. In this case, you need to manage exactly one initialization and one termination per link level using the API __lpi_get_kix_level() call to determine the current link level and to determine whether to instantiate or tear down a given PL/I RTS context. Each subsequent call to __lpi_init() creates a new stacked RTS context, and __lpi_fini_and_return() removes the current context. For example:
int             __lpi_get_kix_level();
CAUTION:
As this is an advanced procedure, do not attempt it unless you are confidant in your understanding of CICS link levels and PL/I API concepts.

Static vs Dynamic Call(s)

PL/I routines can be called statically or dynamically linked. When dynamically linked/called, be sure to consider the design recommendations put forth in the RTS Initialization and Termination section above.