Menu

Calling COBOL programs from Realia compiled COBOL programs

2020-07-15
2021-03-31
  • ABHIJEET CHAVAN

    ABHIJEET CHAVAN - 2020-07-15

    Hi,

    I am trying one test where I am calling Cobc compiled COBOL program from Realia compiled COBOL program.

    I have written a simple COBOL program. without the COB_INIT functions I was getting "libcob: error: cob_init() has not been called" error.

    So I added COB_INIT function. For now I have commented CALL to Program2.

           Identification Division.
           Program-id. Program1.
           Data division.
           working-storage section.
           01 parm-data.
               05 parm-value pic x(256).          
           procedure division.
           DISPLAY 'IN PROGRAM1 ENTRY'.
           move spaces to parm-value.
           call "cob_init"
          * call "Program2" using parm-value.
           call "cob_stop_run"
           stop run.
    

    I have created Program1.obj using realia compiler.
    Then I am trying this Link command to create Program1.exe. but I get below errors.

    link.exe /NOLOGO /INCREMENTAL:NO /SUBSYSTEM:CONSOLE /machine:X86 "/DEBUG:FULL" /ENTRY:_RealiaCOBOLexeentry /OUT:Program1.EXE Program1.obj carclw62.lib /LIBPATH:C:\ccch\AdvantageCARealia33\lib libcob.lib /LIBPATH:C:\OCVS\lib
    Program1.obj : error LNK2001: unresolved external symbol _COB_INIT
    Program1.obj : error LNK2001: unresolved external symbol _COB_STOP_RUN
    Program1.EXE : fatal error LNK1120: 2 unresolved externals
    

    I am using libcob.lib library in the LINK command but I am not sure if I am missing anything else.

    Regards,
    Abhijeet

     

    Last edit: Simon Sobisch 2020-07-15
    • Ralph Linkletter

      This may help.
      It is a program to call cob_init using Windows API(s)
      I do not know where this would fit in with the Realia RTS.
      However the program:
      Loads the coblib-4.dll (LoadLibraryA)
      Gets the address of cob_init (GetProcAddress)
      Calls cob_init (Call Procedure Pointer)
      I have used something similar to it when my .EXE is from PL/I.
      The program is currently in GnuCOBOL form.
      I would make a .DLL from the code (Realia ?)
      Ralph

             IDENTIFICATION DIVISION.                                                 
             PROGRAM-ID. CALLCOBINIT.                                                 
             ENVIRONMENT DIVISION.                                                    
             CONFIGURATION SECTION.                                                   
             SOURCE-COMPUTER. IBM-PC.                                                 
             OBJECT-COMPUTER. IBM-PC.                                                 
             SPECIAL-NAMES.                                                           
                 CALL-CONVENTION 66 IS WINDLL                                         
                 CALL-CONVENTION 74 IS WINAPI.                                        
             INPUT-OUTPUT SECTION.                                                    
             FILE-CONTROL.                                                            
             DATA DIVISION.                                                           
             FILE SECTION.                                                            
             WORKING-STORAGE SECTION.                                                 
             78  ABSOLUTE-RUNTIME-MIN-VAL VALUE 10.                                   
             78  ABSOLUTE-RUNTIME-MAX-VAL VALUE 1000.                                 
             78  LOADLIBRARYA  VALUE 'LoadLibraryA'.                                  
             78  COBINIT       VALUE 'cob_init'.                                      
             78  GetProcAddress  value 'GetProcAddress'.                              
             77  SETUP-STATUS  PIC X(02).                                             
             77  CODESET       PIC X(08) VALUE 'TCODESET'.                            
             77  LOADMOD       PIC X(08).                                             
             77  LENTRY        PIC X(20).                                             
             77  DO-NOTHING    PIC X(01).                                             
             01  PROGRAM-FIELDS.                                                      
                 05  APROC         PROCEDURE-POINTER.                                 
                 05  DLL-BUFFER-LEN             PIC 9(08) COMP-5 VALUE 200.           
                 05  DLL-HANDLE                 PIC 9(08) COMP-5.                     
                 05  DLL-LIBRARY                PIC X(24) VALUE SPACES.               
                 05  DLL-ZERO                   PIC 9(08) COMP-5 VALUE ZERO.          
                 05  DLL-PTR                  USAGE POINTER.                          
                 05  LINK-DLL-PTR               PROCEDURE-POINTER.                    
                 05  LINK-DLL-PTR-X REDEFINES LINK-DLL-PTR PIC X(04).                 
                 05  DLL-NAME.                                                        
                     10  DNAME OCCURS 20 TIMES PIC X(01).                             
                 05  SIMPLEDLL PIC X(24).                                             
                 05  NOCMD     PIC 9(05) COMP-5 VALUE 0.                              
                 05  NOARG     POINTER.                                               
             LINKAGE SECTION.                                                         
             PROCEDURE DIVISION.                                                    
             A-000-MAIN.                                                              
                 MOVE  'LIBCOB-4' TO SIMPLEDLL                                        
                 MOVE SPACES TO DLL-LIBRARY                                           
                 STRING                                                               
                      SIMPLEDLL                    DELIMITED BY SPACE                 
                      '.DLL'                       DELIMITED BY SIZE                  
                      X'00'                        DELIMITED BY SIZE                  
                 INTO                                                                 
                      DLL-LIBRARY                                                     
                 CALL  WINAPI LoadLibraryA                                            
                       USING                                                          
                       BY REFERENCE DLL-LIBRARY                                       
                       RETURNING DLL-HANDLE                                           
                 IF DLL-HANDLE  = 0                                                   
                     GOBACK                                                           
                 END-IF                                                               
                 STRING                                                               
                      'cob_init'                  delimited by size                   
                      X'00'                        DELIMITED BY SIZE                  
                 INTO                                                                 
                      DLL-NAME                                                        
                 CALL WINAPI  GetProcAddress                                          
                       USING                                                          
                       BY VALUE DLL-HANDLE                                            
                       BY REFERENCE DLL-NAME                                          
                       RETURNING LINK-DLL-PTR                                         
                 IF LINK-DLL-PTR-X = LOW-VALUES                                       
                     GOBACK                                                           
                 END-IF                                                               
                 SET NOARG TO NULL                                                    
                 CALL STDCALL LINK-DLL-PTR                                            
                              USING                                                   
                              NOCMD                                                   
                              NOARG                                                   
                 MOVE '1' TO DO-NOTHING.                                              
                 GOBACK. 
      
       

      Last edit: Ralph Linkletter 2020-07-15
  • ABHIJEET CHAVAN

    ABHIJEET CHAVAN - 2020-07-15

    Hi,

    Thank you. I am getting error as below.

    I tried this. I kept just one call in Program1 i.e. call to CALLCOBINIT

       Identification Division.
       Program-id. Program1.
       Data division.
       working-storage section.
       01 parm-data.
           05 parm-value pic x(256).          
       procedure division.
       DISPLAY 'IN PROGRAM1 ENTRY'.
       move spaces to parm-value.
       call "CALLCOBINIT"
       stop run.
    

    compiled CALLCOBINIT.cob with cobc. With realia compiler it gave lots of errors. e.g.
    8 E Unrecognizable word or literal 'IS'
    9 E EBCDIC or STANDARD-N expected; found 'CALL-CONVENTION'
    9 E Unrecognizable word or literal '74'
    9 E Unrecognizable word or literal 'IS'
    9 E EBCDIC or STANDARD-N expected; found '.'
    15 E Unrecognizable word or literal '78'
    15 E Unrecognizable word or literal 'ABSOLUTE-RUNTIME-MIN-VAL'
    15 E Unrecognizable word or literal 'VALUE'

    cobc -c CALLCOBINIT.COB

    Created CALLCOBINIT.dll & CALLCOBINIT.lib
    LINK /NOLOGO /INCREMENTAL:NO /SUBSYSTEM:WINDOWS /DLL /machine:X86 /NODEFAULTLIB:LIBC /DEBUG:FULL /OUT:CALLCOBINIT.DLL CALLCOBINIT.obj libcob.lib /LIBPATH:C:\OCVS\lib
    Creating library CALLCOBINIT.lib and object CALLCOBINIT.exp

    compiled program1 with Realia compiler.
    COBOL /HVWEL:E C:\OCVS\Programs\Program1\Program1.cob C:\OCVS\Programs\Program1\Program1.obj C:\OCVS\Programs\Program1\Program1.lst

    Created Program1.exe. Here I added CALLCOBINIT.lib. Without CALLCOBINIT.lib, I get error"unresolved external symbol _CALLCOBINIT"
    link.exe /NOLOGO /INCREMENTAL:NO /SUBSYSTEM:CONSOLE /machine:X86 "/DEBUG:FULL" /ENTRY:_RealiaCOBOLexeentry /OUT:Program1.EXE Program1.obj CALLCOBINIT.lib carclw62.lib /LIBPATH:C:\ccch\AdvantageCARealia33\Lib

    c:\OCVS\Programs\Program1>Program1.EXE
    IN PROGRAM1 ENTRY
    libcob: error: cob_init() has not been called

    So it seems I need to convert CALLCOBINIT.cob from GnuCobol form to Realia form and try compiling with Realia compiler?

    Regards,

     
    • Simon Sobisch

      Simon Sobisch - 2020-07-16

      Yes, that's the point of this program.

      Obviously (alternative 2) you can start an executable from Realia as another option, something like

          CALL "SYSTEM" USING "cobcrun PROGRAM1 param1 'pa ram 2' par3"
      

      With the benefit of no C calls at all and possible switch between 32/64 bit, but that only privides untyped parameter passing and only a return code back.

      Note: as a third alternative you can also compile your entry programs on the GnuCOBOL side with -fimplicit-init and drop the init call on the C side. In this case you'd either have to do a C call to cob_tidy after your GC compiled program or use STOP RUN there.

       
      • James K. Lowden

        James K. Lowden - 2020-07-16

        compile your entry programs on the GnuCOBOL side with -fimplicit-init and drop the init call

        Why is -fimplicit-init and/or cob_init necessary? Why not make -fimplicit-init automatic, make the flag a no-op, and have cob_init return immediately (doing nothing) when called explicitly?

         
        • Simon Sobisch

          Simon Sobisch - 2020-07-17

          Calling cob_init internally at the start of every program just looks quite wrong.

          Adjusting the code generation in a way that always calls it if necessary (if I remember correctly it already has a simple check now for implicit-init) would be possible, but this initialization has to be considered "dirty", for example libcob could not provide meaningful argv when requested.
          Calling cob_init "external" via C API is a different issue. Actually it is an error to do so before cob_tidy was called. Doing a hard abort leads to caller be fixed once and everything is fine, raising a runtime warning won't break anything and still lead to awareness (if not suppressed or redirected somewhere no one looks at as long as nothing breaks).
          For 4.0 we could change to have cob_init only be used for the C API, returning an int instead of void to possibly be more "library-like" and move the codegen code to cob_init_internal and abort there. We still need to ensure that we ideally keep a compatible C API to the compilers we already have, of course...

          MF has no "only cob_init", how does it handle a double cobcall without a cobtidy in between (GnuCOBOL will abort with a runtime error)?

           

          Last edit: Simon Sobisch 2020-07-17
          • Simon Sobisch

            Simon Sobisch - 2020-07-17

            Rechecked:

            MF has no "only cob_init", how does it handle a double cobcall without a cobtidy in between (GnuCOBOL will abort with a runtime error)?

            Note: cob_extern_init may be called instead of cob_init, that initializes GnuCOBOL only if necessary and sets argc/argv to nothing in this case.

             
          • James K. Lowden

            James K. Lowden - 2020-07-17

            Calling cob_init internally at the start of every program just looks quite wrong.

            If so, what does -fimplicit-init do?

            I remind you both elf and Windows support functions that run
            automatically on load/unload.

            I'm unsure cob_init or cob_exit is actually needed. If needed, I don't see why they can't be automatic. If they can't be automatic, I don't see why they can't be idempotent.

            for example libcob could not provide meaningful argv when requested

            I don't understand this objection.

             
          • James K. Lowden

            James K. Lowden - 2020-07-17

            On Fri, 17 Jul 2020 06:04:45 -0000
            "Simon Sobisch" sf-mensch@users.sourceforge.net wrote:

            Calling cob_init internally at the start of every program just looks
            quite wrong.

            I remind you both elf and Windows support functions that run
            automatically on load/unload.

            I'm also unsure anything in cob_init or cob_exit is actually needed.

            Adjusting the code generation in a way that always calls it if
            necessary (if I remember correctly it already has a simple check
            now for implicit-init) would be possible, but this initialization
            has to be considered "dirty", for example libcob could not provide
            meaningful argv when requested.

            I don't understand that objection.

            Calling cob_init "external" via C API

            is a different issue. Actually it is an error to do so before
            cob_tidy was called. Doing a hard abort leads to caller be fixed once
            and everything is fine, raising a runtime warning won't break
            anything and still lead to awareness (if not suppressed or redirected
            somewhere no one looks at as long as nothing breaks). For 4.0 we
            could change to have cob_init only be used for the C API, returning
            an int instead of void to possibly be more "library-like" and move
            the codegen code to cob_init_internal and abort there. We still need
            to ensure that we ideally keep a compatible C API to the compilers we
            already have, of course...

             
    • Simon Sobisch

      Simon Sobisch - 2020-07-17

      Just another note to the COBINIT program: if you link libcob on the Realia side you don't need to manually load the program via win32api (actually your program should not even start then when libcob is not in PATH.

      To work good you'd have to ensure that cob_init, cob_external_init or whatever libcob function you CALL from Realia:

      • uses the "C" call convention including the return code size (howevr this si done in Realia)
      • ideally also uses a static call-convention, which ensures that the functions are already resolved at link time (= you get a link error message instead a runimte error message)
       
  • ABHIJEET CHAVAN

    ABHIJEET CHAVAN - 2020-07-16

    Yes, I agree, it would be good to have cob_init, cob_tidy, etc run automatically whenever needed.

     
    • Simon Sobisch

      Simon Sobisch - 2020-07-17

      cob_tidy() cleans up everything, if you do STOP RUN within GnuCOBOL it is done automatically, If you only use GOBACK in your main program you can enter it again keeping the same state, which is the way it should be - so there's no option to do a cob_tidy() (or cob_cancel() automatically).
      Note: if you always want to auto-cancel the cobol program afterwards (still leaving the runtime initialized) you may call cob_func() instead, if you want to ensure the init is done but no automatic cancel just compile your program normally and use cob_call() instead of a manual initialization (but be aware that you need to tidy after that before calling the next one with the same approach - or initialize with cob_extern_init as mentioned above.

      Actually this is another point why I feel a cob_init to just go through or return back without any error bad, if you explicit call it twice, you may assume it does the "necessary" cob_tidy() = re-initialize itself.

       
  • ABHIJEET CHAVAN

    ABHIJEET CHAVAN - 2020-07-17

    Thank you for your help. Using the C calling convention removed the linker error I mentioned in my query.

    Where do I see information about cob_extern_init, cob_func, cob_call functions? I do not see details of these functions in the GnuCobol manual.

    Also, may I ask about the details of the call and various parameter data types when I call cob_init or above functions from Cobol programs?

     
    • Simon Sobisch

      Simon Sobisch - 2020-07-17

      Ron is working on a "interface with C" documentation, which will solve all this, until then - minmal stuf is found in the manual (including the init and tidy and dynamic and shared linking) [GnuCOBOL.pdf shipped under "docs"] and you can have a look at libcob/common.h and manually investigate the functions near cob_init (and the redefine cobinit, which is added for MF compatibility, but as it is a define not useable as-is from COBOL).
      Many of the functions have equivalents in Microfocus (see the defines mentioned) so you may have a look for those names in the MF docs, too.

      Note: the data types may map differently in Realia...

       
  • Simon Sobisch

    Simon Sobisch - 2021-03-31

    @abhijeet-chavan Did you made some progress with this project?

     

Anonymous
Anonymous

Add attachments
Cancel





Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.