Calling COBOL Subroutines that Call C Routines

If you are calling COBOL subroutines in Windows, which in turn call C routines, you may want to locate those routines in the calling executable file. You can do this without relinking the runtime by registering your own "sub" function in the C main program. You must add the following declaration to your main program:

typedef    int    (*ACU_SUB_FUNC)(int argc, char **argv);
ACU_SUB_FUNC      *acu_register_sub( ACU_SUB_FUNC *pFunc );

The routine acu_register_sub() registers its argument (pFunc) as an additional "sub" function to call. If pFunc is set to NULL, any existing registration is removed.

The registered function is called just like "sub", but it is called before "sub". Note that "sub" is still called if the registered function returns the constant NotFound.


The following C routine calls a COBOL program which, in turn, calls a C program named "MSGBOX":

#include <stdio.h>
#include <windows.h>
#include "sub.h"

extern     int   __stdcall AcuInitialize( char *cmdLine );
extern    void   __stdcall AcuShutdown(void);

// This is the "sub" function that will be registered
int __cdecl local_sub( int argc, char **argv )
    if ( strcmp( argv[0], "MSGBOX" ) == 0 ) {
       MessageBox( NULL, argv[1], NULL, MB_OK );
       return Okay;
    return NotFound;
// local_sub
    hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
    MessageBox( NULL, "Starting in 'C'", NULL, MB_OK );

// Initialize the runtime using the Visual Basic initializer.
// This prevents the runtime from calling exit() when halting.
    AcuInitialize( "" );

// Install our "sub" handler
   acu_register_sub( local_sub );

// Call the COBOL program. This one takes no parameters
// Assume that this program calls MSGBOX at some point.
// MSGBOX is located in "cblprog".  It will be found
// because "cblprog" got registered with the runtime.
    struct a_cobol_info cblinfo; 
    memset(&cblinfo, 0, sizeof(cblinfo)); 
    cblinfo.a_cobol_info_size = sizeof(cblinfo); 
    cblinfo.pgm_name = "cblprog"; 
    cblinfo.num_params = 0; 
    cblinfo.params = cblinfo.no_stop = 1; 
// De-initialize the runtime.
    MessageBox( NULL, "Back in 'C' - finished", NULL, 
        MB_OK );
    return 0;

Here is the COBOL program called above:

program-id. test.
working-storage section.
77  message-text         pic x(80).
procedure division.
    display "In COBOL program".
    display "Calling MSGBOX"
    move "This is a message" to message-text
    inspect message-text replacing trailing spaces by
    call "MSGBOX" using message-text
    display "Back from MSGBOX".
    display "Press enter to execute STOP RUN ", no
    accept omitted.
    stop run.