
-----------------------------------
btiffin
Fri Feb 01, 2013 6:37 pm

Python embedded in COBOL
-----------------------------------
Well met,

Old guys like COBOL, you should too.  Really.  It might score you a bank, or government gig someday.

[code]
OCOBOL >>SOURCE FORMAT IS FIXED
      *> ***************************************************************
      *> Author:    Brian Tiffin 
      *> Date:      20130126 
      *> Purpose:   Embed Python 
      *> Tectonics: cobc -x cobkat.cob -lpython2.6
      *>     NOTES:    leaks, no Py_DECREF macros called. 
      *> ***************************************************************
       identification division.
       program-id. cobkat.

       data division.
       working-storage section.
       77 python-name          usage pointer.
       77 python-module        usage pointer.
       77 python-dict          usage pointer.
       77 python-func          usage pointer.
       77 python-stringer      usage pointer.
       77 python-args          usage pointer.
       77 python-value         usage pointer.
   
       01 cobol-buffer-pointer usage pointer.    
       01 cobol-buffer         pic x(80)                       based.
       01 cobol-string         pic x(80).

       01 cobol-integer        usage binary-long.

       01 command-line-args    pic x(80).

      *> ***************************************************************
       procedure division.
      *> let python scan current work dir for scripts
       set environment "PYTHONPATH" to "."

      *> init the engine, hint if link lib problem
       call "Py_Initialize"
           on exception
               display "link cobpy with -lpython" end-display
       end-call
       
      *> Python likes module names in Unicode
       call "PyUnicodeUCS4_FromString" using
           by reference "pythonfile" & x"00"
           returning python-name
           on exception
               display "unicode problem" end-display
       end-call

      *> import the module, using PYTHONPATH 
       call "PyImport_Import" using
           by value python-name
           returning python-module
           on exception
               display "this would be borked" end-display
       end-call

       if python-module equal null
           display "no pythonfile.py in PYTHONPATH" end-display
       end-if

      *> within the module object, an attribute is "pthonfunction"
       call "PyObject_GetAttrString" using
           by value python-module
           by reference "pythonfunction" & x"00"
           returning python-func
           on exception continue
       end-call

      *>
      *> error handling now skimped out on
      *>

      *> pythonfunction takes a single argument
       call "PyTuple_New" using
           by value 1
           returning python-args
       end-call
  
      *> of type long, hard coded to the ultimate answer 
       call "PyLong_FromLong" using
           by value 42
           returning python-value
       end-call

      *> set first (only) element of the argument tuple 
       call "PyTuple_SetItem" using
           by value python-args
           by value 0
           by value python-value
       end-call

      *> call the function, arguments marshalled for Python 
       call "PyObject_CallObject" using
           by value python-func
           by value python-args
           returning python-value
       end-call

      *> we know we get a long back, hopefully 1764
       call "PyLong_AsLong" using
           by value python-value
           returning cobol-integer 
       end-call
       display "Python returned: " cobol-integer end-display

      *> ************************************************************ *<
      *> Interface to a function taking string and returning string
       call "PyObject_GetAttrString" using
           by value python-module
           by reference "pythonstringer" & x"00"
           returning python-stringer
       end-call

       call "PyTuple_New" using
           by value 1
           returning python-args
       end-call
  
      *> Use the OpenCOBOL command argument
       accept command-line-args from command-line end-accept 
       call "PyString_FromString" using
           by reference
               function concatenate(
                   function trim(command-line-args)
                   x"00")
           returning python-value
       end-call

      *> Set the function argument tuple to point to the cli args 
       call "PyTuple_SetItem" using
           by value python-args
           by value 0
           by value python-value
       end-call
 
      *> call the "pythonstringer" function
       call "PyObject_CallObject" using
           by value python-stringer
           by value python-args
           returning python-value
       end-call

      *> return as String (with pythonstringer MD5 hex digest tacked on)
       call "PyString_AsString" using
           by value python-value
           returning cobol-buffer-pointer 
       end-call

      *> one way of removing null bytes and pulling data out of C
       set address of cobol-buffer to cobol-buffer-pointer
       string
           cobol-buffer delimited by x"00" 
           into cobol-string
       end-string
       display "Python returned: " cobol-string end-display

      *> and clear out 