Alexandre
Alexandre

Reputation: 2025

Cobol interface with C

So, i'm work with C and OpenCobol, and, I whant to know if have an way to get the value of a internal cobol source...

for example (based on sample of this link): http://www.opencobol.org/modules/bwiki/index.php?cmd=read&page=UserManual%2F2_3

---- say.cob ---------------------------
      IDENTIFICATION DIVISION.
      PROGRAM-ID. say.

      ENVIRONMENT DIVISION.
      DATA DIVISION.

      WORKING-STORAGE SECTION.
      01 TESTE PIC 9(9) VALUE ZEROS.

      LINKAGE SECTION.
      01 HELLO PIC X(6).
      01 WORLD PIC X(6).

      PROCEDURE DIVISION USING HELLO WORLD.
          MOVE 456 TO TESTE.
          DISPLAY TESTE.
          DISPLAY HELLO WORLD.

         *> RETURN TESTE. ??????

          EXIT PROGRAM.
----------------------------------------

And, the C code when I use is that:

---- hello.c ---------------------------

#include <stdio.h>
#include <libcob.h>

extern int say(char *hello, char *world);

int
main()
{
  int ret;
  char hello[6] = "Hello ";
  char world[6] = "World!";

  cob_init(0, NULL);

  ret = say(hello, world); // return the 000000456 ?????????? 
  // How to make this :(

  return ret;
}
----------------------------------------

Or, have an whay to get the cobol variable, something like this:

// ... code ...
int value = cob_getvar(TESTE);
// ... code ...

Upvotes: 2

Views: 2877

Answers (2)

Brian Tiffin
Brian Tiffin

Reputation: 4126

Alexandre;

OpenCOBOL 2.0 will have FUNCTION-ID allowing for things like

MOVE FUNCTION nextbigthing(args) TO cobol-working-store

Until it is released though, we are "limited" to CALL, ENTRY, PROGRAM-ID and the like.

For an example of some low level function pointer related things, take a look at

http://opencobol.add1tocobol.com/#what-stock-call-library-does-opencobol-offer

which includes a snippet for setting error handlers and exit procedures. Scan that with an eye on

  • PROCEDURE-POINTER
  • ENTRY
  • SET proc-ptr TO ENTRY "link-name"
  • CALL ... USING ... RETURNING

with the caveat, that this is one way. There are others. The ENTRY lines can be full on PROGRAM-ID subprograms, etc. Section 5 of the OpenCOBOL FAQ is rife with routines that pass data back and forth from other languages and link libraries.

Also, look to cob_field in libcob/common.h. The C code generated by CALL sets up an array of the COBOL fields of the arguments, along with the actual call frame, and these COBOL field structures can be accessed from C functions through cob_module.

errorproc.cob

   >>SOURCE FORMAT IS FIXED
  *****************************************************************
  * OpenCOBOL demonstration
  * Author:  Brian Tiffin
  * Date:    26-Jun-2008
  * History:
  *     03-Jul-2008
  *     Updated to compile warning free according to standards
  * Purpose:
  *     CBL_ERROR_PROC and CBL_EXIT_PROC call example
  *     CBL_ERROR_PROC installs or removes run-time error procedures
  *     CBL_EXIT_PROC installs or removes exit handlers
  *     Also demonstrates the difference between Run time errors
  *     and raised exceptions.  Divide by zero raises an
  *     exception, it does not cause a run time error.
  * NB:
  *     Please be advised that this example uses the functional but
  *     now obsolete ENTRY verb.  Compiling with -Wall will display
  *     a warning.  No warning will occur using -std=MF
  * Tectonics: cobc -x errorproc.cob
   identification division.
   program-id. error_exit_proc.

   data division.
   working-storage section.
  * entry point handlers are procedure addresses
   01  install-address   usage is procedure-pointer.
   01  install-flag      pic 9 comp-x value 0.
   01  status-code       pic s9(9) comp-5.

  * exit handler address and priority (prio is IGNORED with OC1.1)
   01  install-params.
       02 exit-addr      usage is procedure-pointer.
       02 handler-prio   pic 999 comp-x.

  * indexing variable for back scannning error message strings
   01  ind               pic s9(9) comp-5.

  * work variable to demonstrate raising exception, not RTE
   01  val               pic 9.

  * mocked up error procedure reentrancy control, global level
   01  once              pic 9 value 0.
       88 been-here            value 1.

  * mocked up non-reentrant value
   01  global-value      pic 99 value 99.

  * LOCAL-STORAGE SECTION comes into play for ERROR_PROCs that
  *   may themselves cause run-time errors, handling reentry.
   local-storage section.
   01  reenter-value     pic 99 value 11.

  * Linkage section for the error message argument passed to proc
  * By definition, error messages are 325 alphanumeric
   linkage section.
   01  err-msg           pic x(325).

  * example of OpenCOBOL error and exit procedures
   procedure division.

  * Demonstrate problem installing procedure
  * get address of WRONG handler.  NOTE: Invalid address
   set exit-addr to entry "nogo-proc".

  * flag: 0 to install, 1 to remove
   call "CBL_EXIT_PROC" using install-flag
                              install-params
                        returning status-code
   end-call.
  * status-code 0 on success, in this case expect error.
   if status-code not = 0
       display
           "Intentional problem installing EXIT PROC"
           ", Status: " status-code
       end-display
   end-if.

  * Demonstrate install of an exit handler
  * get address of exit handler
   set exit-addr to entry "exit-proc".

  * flag: 0 to install, 1 to remove
   call "CBL_EXIT_PROC" using install-flag
                              install-params
                        returning status-code
   end-call.
  * status-code 0 on success.
   if status-code not = 0
       display
           "Problem installing EXIT PROC"
           ", Status: " status-code
       end-display
       stop run
   end-if.

  * Demonstrate installation of an error procedure
  * get the procedure entry address
   set install-address to entry "err-proc".

  * install error procedure. install-flag 0 installs, 1 removes
   call "CBL_ERROR_PROC" using install-flag
                               install-address
                         returning status-code
   end-call.
  * status-code is 0 on success.
   if status-code not = 0
       display "Error installing ERROR PROC" end-display
       stop run
   end-if.

  * example of error that raises exception, not a run-time error
   divide 10 by 0 giving val end-divide.
  * val will be a junk value, use at own risk

   divide 10 by 0 giving val
       on size error display "DIVIDE BY ZERO Exception" end-display
   end-divide.

  * intentional run-time error
   call "erroneous" end-call.           *> ** Intentional error **

  * won't get here.  RTS error handler will stop run
   display
       "procedure division, following run-time error"
   end-display.
   display
       "global-value: " global-value
       ", reenter-value: " reenter-value
   end-display.

   exit program.
  *****************************************************************

  *****************************************************************
  * Programmer controlled Exit Procedure:
   entry "exit-proc".

   display
       "**Custom EXIT HANDLER (will pause 3 and 0.5 seconds)**"
   end-display.

  * sleep for 3 seconds
   call "C$SLEEP" using "3" end-call.
  * demonstrate nanosleep; argument in billionth's of seconds
  *   Note: also demonstrates OpenCOBOL's compile time
  *         string catenation using ampersand;
  *         500 million being one half second
   call "CBL_OC_NANOSLEEP" using "500" & "000000" end-call.

   exit program.

  *****************************************************************
  * Programmer controlled Error Procedure:
   entry "err-proc" using err-msg.

   display "**ENTER error procedure**" end-display.

  * These lines are to demonstrate local and working storage
   display
       "global-value: " global-value
       ", reenter-value: " reenter-value
   end-display.
  * As reenter-value is local-storage
  *  the 77 will NOT display on rentry, while the global 66 will
   move 66 to global-value.
   move 77 to reenter-value.

  * Process err-msg.
  * Determine Length of error message, looking for null terminator
   perform varying ind from 1 by 1
       until (err-msg(ind:1) = x"00") or (ind = length of err-msg)
           continue
   end-perform.
   display err-msg(1:ind) end-display.

  * demonstrate trapping an error caused in error-proc
   if not been-here then
       set been-here to true
       display "Cause error while inside error-proc" end-display
       call "very-erroneous" end-call        *> Intentional error
   end-if.

  * In OpenCOBOL 1.1, the return-code is local and does
  *   not influence further error handlers
  *move 1 to return-code.
   move 0 to return-code.

   display "**error procedure EXIT**" end-display.

   exit program. 

Upvotes: 2

David Gorsline
David Gorsline

Reputation: 5018

Look at page 7-7 of the OpenCOBOL Programmers Guide. For the data that you want to pass back to your C program, add another argument and pass it by reference to the COBOL program. Declare your TESTE as binary to match the C declaration. You can also pass back the automatically-defined RETURN-CODE, if you like. So your COBOL would be something like this:

  DATA DIVISION.
  LINKAGE SECTION.
  01 HELLO PIC X(6).
  01 WORLD PIC X(6).
  01 TESTE PIC S9(9) USAGE BINARY-LONG.
  PROCEDURE DIVISION USING 
      BY VALUE HELLO
      BY VALUE WORLD
      BY REFERENCE TESTE.
  0000-MAIN-ROUTINE.
      MOVE 456 TO TESTE
      MOVE 1 TO RETURN-CODE
      GOBACK.

And in your calling program:

int teste;
int returnCode;
char hello[6] = "Hello ";
char world[6] = "World!";

cob_init(0, NULL);
returnCode = say(hello, world, &teste); 

Upvotes: 2

Related Questions