For users of IBM Enterprise COBOL for z/OS, you may want to integrate Python into your COBOL jobs, for example to integrate AI/ML workloads using the Python AI Toolkit for IBM z/OS. Let’s look at some ways that we can have interoperability between Python and 64-bit COBOL. This blog will be showing examples of how to do this when your COBOL is a 64-bit application, and we will explore calling 31-bit COBOL in another blog.
Prerequisites
You will need both of the following products installed & setup:
IBM Open Enterprise SDK for Python
- For Python 3.11, PTF UI98927 is required
- For Python 3.12, PTF UI98924 is required
- No prerequisites for Python 3.13
IBM Enterprise COBOL for z/OS
64-bit COBOL calling Python
Python has a C API which can be used to embed the Python interpreter inside your COBOL program. The IBM Open Enterprise SDK for Python includes the side deck for these functions, so you can directly call them from your COBOL program as long as Python’s libpython is contained in your LIBPATH. A sample COBOL program which calls Python:
cobtest.cbl:
IDENTIFICATION DIVISION.
PROGRAM-ID. "COBTEST".
DATA DIVISION.
WORKING-STORAGE SECTION.
01 pyrun PIC u(80) VALUE z'print("Hello, world")'.
PROCEDURE DIVISION.
CALL "Py_Initialize"
CALL "PyRun_SimpleString" USING
BY REFERENCE pyrun
END-CALL
CALL "Py_Finalize"
STOP RUN.
Within this simple COBOL program, we can see that there are 3 Python functions being called:
- Py_Initialize – This function must be called to initialize the Python interpreter.
- PyRun_SimpleString – This function runs our Python code, and we pass in the Python code using a variable named pyrun – a UTF-8 variable which is compatible with Python. This variable is holding the value print(“Hello, world”), so running this COBOL program will be print that.
- Py_Finalize – This destroys all Python interpreters and cleans up any memory used. It must be called before trying to run Py_Initialize again, or before the program ending.
You can use the following sample to compile this COBOL program:
cob2 -q64 -q"pgmname(longmixed)" cobtest.cbl -o cobtest ${PYTHON_INSTALL_PATH}/lib/libpython3.13.x
Note that libpython3.13.x side deck is dependent on the version of Python you have installed and will be named appropriately.
In this example, we used PyRun_SimpleString to embed and run Python code directly. This is not a requirement however, as any parts of Pythons C API can be used. There is another longer code sample found here which shows both how to use Pythons C API in more depth, and how packages from the Python AI Toolkit for IBM z/OS can be used from COBOL.
Python calling 64-bit COBOL
Since Python is an interpreted language, we’ll be using Pythons built in library ctypes to load the COBOL module and run the functions dynamically. Because of this, the COBOL module needs to be compiled as a DLL. We have a sample COBOL program here:
cobtest.cbl
IDENTIFICATION DIVISION.
PROGRAM-ID. 'COBTEST'.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
DATA DIVISION.
FILE SECTION.
WORKING-STORAGE SECTION.
LINKAGE SECTION.
01 PARAM1 PIC S9(9) USAGE IS BINARY.
01 PARAM2 PIC S9(9) USAGE IS BINARY.
01 RETCODE PIC S9(9) USAGE IS BINARY.
PROCEDURE DIVISION USING BY VALUE PARAM1
BY VALUE PARAM2
RETURNING RETCODE.
ADD PARAM1 to RETCODE
ADD PARAM2 to RETCODE
GOBACK.
This defines a function that has two inputs, param1 and param2, and returns the sum of these inputs. To compile this, we can run the following:
cob2 -q64 -q"dll" -q"pgmname(longmixed)" -bdll -qexportall cobtest.cbl -o cobtest.so
Once we have our COBOL compiled as a shared library, we can then load it up in Python.
import ctypes
mydll = ctypes.CDLL("./cobtest.so")
# Set up the function argument and return types
mydll.COBTEST.argtypes = [ctypes.c_int, ctypes.c_int]
mydll.COBTEST.restype = ctypes.c_int
result = mydll.COBTEST(5,6)
assert result == 11 # Sum of 5 + 6 == 11
To load the DLL in Python, ctypes contains the CDLL function that specifies a path to a DLL. Then we have access to all functions contained within this DLL. However, we additionally need to specify both the number of arguments, the types it accepts, and the type that it returns so that Python can properly call it. In this case, since the COBOL code returns the sum of its inputs, when we call it we can verify that this is the correct output.
And that’s all that’s required to do interoperability between Python and COBOL. If you would like to view the sample code used for this blog, it’s also available on Github. Lastly, there are also some additional related blogs you may be interested in: