Menu

Calling GNUCobol from Java

Anonymous
2015-09-09
2021-07-15
1 2 > >> (Page 1 of 2)
  • Anonymous

    Anonymous - 2015-09-09

    Hi,

    Is it possible to call GNUCobol from java? or to call Java from cobol?

     
  • Brian Tiffin

    Brian Tiffin - 2015-09-09

    Yes.

    GnuCOBOL can easily link to anything C, and JNI is available. If you are doing a large integration, the SWIG tool would likely be very smart place to start. COBOL to C, then SWIG the C to and from Java.

    There is a grand contribution to GnuCOBOL by László Erdős, COBJAPI, direct access to AWT features from COBOL user defined functions. Very well documented, loads of examples.

    http://sourceforge.net/p/open-cobol/discussion/contrib/thread/cf38bb95/

    Cheers

     
  • Anonymous

    Anonymous - 2015-09-10

    Thanks Brian,

    i have looked at SWIG looks like this is going to be easier than i thought.

     
  • Brian Tiffin

    Brian Tiffin - 2015-09-10

    Yeah, it does make it pretty easy. I'll put a sample in the FAQ. A couple of issues.

    • You can't SWIG from COBOL, you'll need to go through the generated C.
    • use -g to have the generated C files hang around, or use -save-temps
    • The prototypes are in the program.c files, not the the .c.h or c.l.h, so that's a pain, meaning there is no lazy mode and simply including the header in the SWIG interface file, the entry points will need to be listed explicitly in the .i file.
    • .i files are overwritten by the preprocessor, so there needs to be an extra name, program-swig.i and not a SWIG program.i, as GnuCOBOL will use program.i as part of its internal text preprocessor.

    And the big one:

    • GnuCOBOL mangles variable names beyond recognition. There is no way around that one at this time. 01 important-data pic x(80) external. Won't cut it, the .c.h file (or .c.l.h or .c.l1.h .c.l2.h...) will have a generated name akin to b_5, or b_17, and the generated name will change on each compile, and there is no consistent ryhme or reason to the naming (well there is, but it changes with each new entry in working-store, and a host of other factors due to the abstract symbolic tree used by the compiler). So to get at data, you need to write a program and return it (plus it's length) or write a C function that squirrels into linkage section by going through cob_global to cob_module and the shadow CALL parameter cob_field array, and even this won't be by COBOL name in C, it'll be by position in CALL arguments.

    Cheers,
    Brian

     
  • Gary Cowell

    Gary Cowell - 2016-01-14

    I'm very interested also in being able to call Gnu COBOL modules from Java with JNI

    Our current application uses Micro Focus with its runtime system jar.

    I suspect though, that's overkill for what we need.

    We need to instantiate a COBOL runtime, then invoke a module passing LINKAGE items as byte arrays.

    So, for example we might have

    LINKAGE
    01 some-item
    03 ... PIC
    03 ... PIC
    03 ... PIC

    procedure division using some-item.
    a-main section.
    display 'foo'
    goback.

    we already have JAVA classes to map some-item to subordinate data items in JAVA, and to supply the whole thing as a byte array.

    So in JAVA we need to call 'COBOL' passing a reference (pointer) to our byte array.

    Then, if the COBOL program changes storage within the some-item , we see it back in JAVA when the call is finished.

    So, I don't need to access working-storage items directly, just pass the reference pointer of our byte array to the called program. SWIG seems overkill for this at first glance.

    Works quite well with Micro Focus, but they have helper classes in a jar to make this easy (new ParameterList, and then adding POINTER values to the call parameter list).

    I don't know JAVA half as well as COBOL though, an example or two, or some documentation on the topic would be super.

     
  • Brian Tiffin

    Brian Tiffin - 2016-01-15

    Was Gary Cowell's post deleted on purpose? By mistake? Or is this a SourceForge glitch? The summary screen still shows a link (though it won't once I make this post) and I got an email copy, so can reproduce his entry, but I'm not seeing it here. Don't want to just add it back in if it was deleted on purpose.

    Curious,
    Brian

     

    Last edit: Brian Tiffin 2016-01-15
  • Bill Woodger

    Bill Woodger - 2016-01-15

    Brian, I can see it now, and I could see it seven hours ago just befeore I got to bed. It is marked as "20 hours ago"

     
    • Simon Sobisch

      Simon Sobisch - 2016-01-15

      I can't see it. Please repost it if you see it.

       
      • Bill Woodger

        Bill Woodger - 2016-01-15

        Repost from copy/paste of what I can see from original post by Gary Cowel.

        Odd. I've noticed something possibly simimlar (appear on summary page, not in list of posts within acrual area) with some anonymous posts over the last few months. Sorts itself out after some time with those, so didn't think much of it. Could be a different issue.


        I'm very interested also in being able to call Gnu COBOL modules from Java with JNI

        Our current application uses Micro Focus with its runtime system jar.

        I suspect though, that's overkill for what we need.

        We need to instantiate a COBOL runtime, then invoke a module passing LINKAGE items as byte arrays.

        So, for example we might have

        LINKAGE
        01 some-item
        03 ... PIC
        03 ... PIC
        03 ... PIC

        procedure division using some-item.
        a-main section.
        display 'foo'
        goback.

        we already have JAVA classes to map some-item to subordinate data items in JAVA, and to supply the whole thing as a byte array.

        So in JAVA we need to call 'COBOL' passing a reference (pointer) to our byte array.

        Then, if the COBOL program changes storage within the some-item , we see it back in JAVA when the call is finished.

        So, I don't need to access working-storage items directly, just pass the reference pointer of our byte array to the called program. SWIG seems overkill for this at first glance.

        Works quite well with Micro Focus, but they have helper classes in a jar to make this easy (new ParameterList, and then adding POINTER values to the call parameter list).

        I don't know JAVA half as well as COBOL though, an example or two, or some documentation on the topic would be super.

         

        Last edit: Bill Woodger 2016-01-15
        • Brian Tiffin

          Brian Tiffin - 2016-01-15

          Thanks, Bill.

          Apologies to Gary. It's an anomaly, Gary, hopefully not to happen again.

          Cheers,
          Brian

           
  • Gary Cowell

    Gary Cowell - 2016-01-15

    I didn't delete it. I was really confused as to why I could see 5 posts in the thread, last one by me, but no actual post. My profile page shows me having made the post, but yet ... no post. And I can't remember what I wrote exactly. I don't mind if you post it again, or, I can write another one.

    I think I'll have to start Ctrl-A-C-V these postings to my text editor :)

     
  • Brian Tiffin

    Brian Tiffin - 2016-01-15

    Have you seen COBJAPI yet, Gary? László did a superb job at easing access into Java space with User Defined Functions.

    http://sourceforge.net/p/open-cobol/contrib/HEAD/tree/trunk/tools/cobjapi/

    It's one option. There are others.

    And I'd recommend a second look at SWIG. If the objective is calling into COBOL, SWIG is the ticket. As it is all compiled to native library calls, the overhead baggage is pretty small. The SWIG tooling is rather large, as it covers a lot of bases, but the end product is pretty close to what a hand crafted solution would end up being, just easier on the brain.

    http://open-cobol.sourceforge.net/faq/index.html#does-gnucobol-work-with-swig has a Java sample, and the output binaries are pretty tight. I'll try and remember to add some directory size listings to that entry soon.

    The whole thing breaks down if you want to leverage Java from COBOL, as that is not the goal of the SWIG tool, I'd look to COBJAPI for that.

    Cheers,
    Brian

     
  • Gary Cowell

    Gary Cowell - 2016-01-15

    Also, I've started to look into JNA rather than JNI. JNA looks easier to code for. I think I'll do a couple of simple examples, and see how it goes.

     
    • Brian Tiffin

      Brian Tiffin - 2016-01-15

      +1 on JNA being an avenue worth travelling.

      I might even try and put a sample entry in the FAQ someday soon.

      Cheers,
      Brian

       
  • Oscar

    Oscar - 2016-01-15

    Hi Gary,

    Why don't you try SWIG, i have attached the example on FAQ by Brian just do make java, java main. then you can take it from there when i was looking at the example my only challenge was passing data to cobol from java and back to java as the examples only invokes cobol from java.

     

    Last edit: Oscar 2016-01-15
  • Gary Cowell

    Gary Cowell - 2016-01-15

    Will check it out, thanks

     
  • Gary Cowell

    Gary Cowell - 2016-01-18

    I made this example of calling GnuCOBOL program from Java using JNA. I built it with JNA 4.2.1 and Java 8.

    COBOL program, cobsubtest.cbl

            identification division.
            program-id. cobsubtest.
            data division.
            linkage section.
            01  PassedParameter pic X(72).
            procedure division using
            by reference     PassedParameter.
            A-Main Section.
                    display 'Starting cobsubtest.cbl'
                    display 'Called With [' PassedParameter ']'
                    move 2 TO return-code.
                    goback.
    

    JAVA program jnacob.java:

    import com.sun.jna.*;
    
    /*
     * libcob interface, initialising GnuCOBOL run time
     */
    interface libcob extends Library {
            libcob INSTANCE = (libcob) Native.loadLibrary("cob", libcob.class);
            void cob_init(int argc, Pointer argv);
    }
    
    /*
     * COBOL program interface, single program
     */
    interface subtest extends Library {
            subtest INSTANCE = (subtest) Native.loadLibrary("cobsubtest", subtest.class);
            int cobsubtest(Pointer aValue);
    }
    
    public class jnacob {
            public static void main(String[] args) {
    
                    /*
                     * try and initialise the GnuCOBOL run time
                     * calling cob_init with no parameters
                     */
                    try {
                            libcob.INSTANCE.cob_init(0, null);
                    } catch (UnsatisfiedLinkError e) {
                            System.out.println("Libcob Exception" + e);
                    }
    
                    /*
                     * call a GnuCOBOL program, passing a PIC X(72)
                     * space filled
                     */
                    try {
                            // JAVA string
                            String stringThing = new String("We Did It!");
    
                            // make a Pointer and space fill
                            // we use -1 on the pointer write to strip
                            // the C null string terminator
                            Pointer pointer;
                            pointer = new Memory(72);
                            byte space = 32;
                            pointer.setMemory(0,72,space);
                            byte[] data = Native.toByteArray(stringThing);
                            pointer.write(0, data, 0, data.length - 1);
    
                            // call the GnuCOBOL program
                            int rc=subtest.INSTANCE.cobsubtest(pointer);
    
                            // display return-code
                            System.out.print("COBOL Return Code ");
                            System.out.println(rc);
    
                    } catch (UnsatisfiedLinkError e) {
                            System.out.println("subtest Exception" + e);
                    }
    
            }
    }
    

    Build and execute:
    Need to have jna-4.2.1.jar in current directory (or, elsewhere, modify classpath as appropriate)

    javac -classpath ./jna-4.2.1.jar jnacob.java
    cobc -o libcobsubtest.so cobsubtest.cbl
    java -classpath ./jna-4.2.1.jar:. jnacob
    

    Will be doing more work to show COBOL sub routines mutating storage, and sharing that storage between COBOL modules.

    Hope this helps someone get started.

     

    Last edit: Simon Sobisch 2016-01-18
  • Gary Cowell

    Gary Cowell - 2016-01-18

    Updated now with mutation showing between sub programs (didn't really expect this wouldn't work, but it's worth showing):

    javac -classpath ./jna-4.2.1.jar jnacob.java
    cobc -o libcobsubtest.so cobsubtest.cbl
    cobc -o libcobsubtest2.so cobsubtest2.cbl
    java -classpath ./jna-4.2.1.jar:. jnacob
    

    cobsubtest.cbl

            identification division.
            program-id. cobsubtest.
            data division.
            linkage section.
            01  PassedParameter pic X(72).
            procedure division using
            by reference     PassedParameter.
            A-Main Section.
                    display 'Starting cobsubtest.cbl'
                    display 'Called With ['  PassedParameter ']'
    
                    move 'We changed it!' to PassedParameter
                    move 2 TO return-code.
    
                    goback.
    

    cobsubtest2.cbl

            identification division.
            program-id. cobsubtest2.
            data division.
            linkage section.
            01  PassedParameter pic X(72).
            procedure division using
            by reference     PassedParameter.
            A-Main Section.
                    display 'Starting cobsubtest2:'
                    display 'Called With [' PassedParameter ']'
                    move 8 TO return-code.
                    goback.
    

    jnacob.java

    import com.sun.jna.*;
    
    /*
     * libcob interface, initialising GnuCOBOL run time
     */
    interface libcob extends Library {
            libcob INSTANCE = (libcob) Native.loadLibrary("cob", libcob.class);
            void cob_init(int argc, Pointer argv);
    }
    
    /*
     * first COBOL program interface, single program
     */
    interface subtest extends Library {
            subtest INSTANCE = (subtest) Native.loadLibrary("cobsubtest", subtest.class);
            int cobsubtest(Pointer aValue);
    }
    
    /*
     * second COBOL program interface, single program
     */
    interface subtest2 extends Library {
            subtest2 INSTANCE = (subtest2) Native.loadLibrary("cobsubtest2", subtest2.class);
            int cobsubtest2(Pointer aValue);
    }
    
    public class jnacob {
            public static void main(String[] args) {
    
                    /*
                     * try and initialise the GnuCOBOL run time
                     * calling cob_init with no parameters
                     */
                    try {
                            libcob.INSTANCE.cob_init(0, null);
                    } catch (UnsatisfiedLinkError e) {
                            System.out.println("Libcob Exception" + e);
                    }
    
                    /*
                     * call a GnuCOBOL program, passing a PIC X(72)
                     * space filled
                     */
                    try {
                            // JAVA string
                            String stringThing = new String("We Did It!");
    
                            // make a Pointer and space fill
                            Pointer pointer;
                            pointer = new Memory(72);
                            byte space = 32;
                            pointer.setMemory(0,72,space);
                            byte[] data = Native.toByteArray(stringThing);
                            pointer.write(0, data, 0, data.length - 1);
    
                            int rc;
    
                            // call the GnuCOBOL program
                            rc=subtest.INSTANCE.cobsubtest(pointer);
    
                            // display return-code
                            System.out.print("COBOL Return Code ");
                            System.out.println(rc);
    
                            // call the second test
                            rc=subtest2.INSTANCE.cobsubtest2(pointer);
                            System.out.print("COBOL Return Code ");
                            System.out.println(rc);
    
                    } catch (UnsatisfiedLinkError e) {
                            System.out.println("subtest Exception" + e);
                    }
            }
    }
    

    Result:

    Starting cobsubtest.cbl
    Called With [We Did It!                                                              ]
    COBOL Return Code 2
    Starting cobsubtest2:
    Called With [We changed it!                                                          ]
    COBOL Return Code 8
    
     

    Last edit: Simon Sobisch 2016-01-18
    • Anonymous

      Anonymous - 2020-06-24

      In this example i can see the data being passed between two cobol programs,

      Here i can see the java program accepting the return-code from cobol program rc=subtest.INSTANCE.cobsubtest(pointer);

      But now i want to know how do we access this or print or display data/value inside pointer on our java program? i want to pass value to cobol program the receive it and then use it on my java program right now i dont know how to access the data inside pointer

      Can someone please help me?

       
      • Brian Tiffin

        Brian Tiffin - 2020-06-25

        See https://java-native-access.github.io/jna/4.2.1/com/sun/jna/Pointer.html

        Tons of access methods, read(...) is likely what you are looking for.

        Cheers,
        Blue

         
        • Anonymous

          Anonymous - 2020-06-25

          Thanks Brian,

          I just hacked this around, here is a working version.

          import com.sun.jna.*;
          
          /*
          * libcob interface, initialising GnuCOBOL run time
          */
          interface libcob extends Library {
                  libcob INSTANCE = (libcob) Native.loadLibrary("libcob-4", libcob.class);
                  void cob_init(int argc, Pointer argv);
          }
          
          /*
          * first COBOL program interface, single program
          */
          interface subtest extends Library {
                  subtest INSTANCE = (subtest) Native.loadLibrary("cobsubtest",
          subtest.class);
                  int cobsubtest(Pointer aValue);
          }
          
          /*
          * second COBOL program interface, single program
          */
          interface subtest2 extends Library {
                  subtest2 INSTANCE = (subtest2) Native.loadLibrary("cobsubtest2",
          subtest2.class);
                  int cobsubtest2(Pointer aValue);
          }
          
          public class jnacob {
                  public static void main(String[] args) {
          
                          /*
                           * try and initialise the GnuCOBOL run time
                           * calling cob_init with no parameters
                           */
                          try {
                                  libcob.INSTANCE.cob_init(0, null);
                          } catch (UnsatisfiedLinkError e) {
                                  System.out.println("Libcob Exception" + e);
                          }
          
                          /*
                           * call a GnuCOBOL program, passing a PIC X(72)
                           * space filled
                           */
                          try {
                                  // JAVA string
                                  String stringThing = new String("We Did It!");
          
                                  // make a Pointer and space fill
                                  Pointer pointer;
                                  pointer = new Memory(72);
                                  byte space = 32;
                                  pointer.setMemory(0,72,space);
                                  byte[] data = Native.toByteArray(stringThing);
                                  pointer.write(0, data, 0, data.length - 1);
          
                                  int rc;
          
                                  // call the GnuCOBOL program
                                  rc=subtest.INSTANCE.cobsubtest(pointer);
          
                                  byte[] data_2 = new byte[72];
                                  ((Pointer)pointer).read(0, data_2, 0, data_2.length);
          
          
                                  String coboldata = new String(data_2);
                                  System.out.println("data from cobol : " + coboldata);
          
          
                                  // display return-code
                                  System.out.print("COBOL Return Code ");
                                  System.out.println(rc);
          
                                  // call the second test
                                  rc=subtest2.INSTANCE.cobsubtest2(pointer);
                                  System.out.print("COBOL Return Code ");
                                  System.out.println(rc);
          
                          } catch (UnsatisfiedLinkError e) {
                                  System.out.println("subtest Exception" + e);
                          }
                  }
          }
          
           
          • thomas

            thomas - 2020-06-25

            That program uses some old deprecated method to load the library, here is an improved program.

            import com.sun.jna.*;
            
            /*
            * libcob interface, initialising GnuCOBOL run time
            */ 
            interface libcob extends Library {
                    libcob INSTANCE = Native.load("libcob-4", libcob.class);
            
                    void cob_init(int argc, Pointer argv);
            }
            
            /*
            * first COBOL program interface, single program
            */
            interface subtest extends Library {
                    subtest INSTANCE = Native.load("cobsubtest", subtest.class);
                    int cobsubtest(Pointer aValue);
            }
            
            /*
            * second COBOL program interface, single program
            */
            interface subtest2 extends Library {
            
                    subtest2 INSTANCE = Native.load("cobsubtest2", subtest2.class);
                    int cobsubtest2(Pointer aValue);
            }
            
            public class jnacob {
                    public static void main(String[] args) {
            
                            /*
                             * try and initialise the GnuCOBOL run time
                             * calling cob_init with no parameters
                             */
                            try {
                                    libcob.INSTANCE.cob_init(0, null);
                            } catch (UnsatisfiedLinkError e) {
                                    System.out.println("Libcob Exception" + e);
                            }
            
                            /*
                             * call a GnuCOBOL program, passing a PIC X(72)
                             * space filled
                             */
                            try {
                                    // JAVA string
                                    String stringThing = new String("We Did It!");
            
                                    // make a Pointer and space fill
                                    Pointer pointer;
                                    pointer = new Memory(72);
                                    byte space = 32;
                                    pointer.setMemory(0,72,space);
                                    byte[] data = Native.toByteArray(stringThing);
                                    pointer.write(0, data, 0, data.length - 1);
            
                                    int rc;
            
                                    // call the GnuCOBOL program
                                    rc=subtest.INSTANCE.cobsubtest(pointer);
            
                                    byte[] data_2 = new byte[72];
                                    pointer.read(0, data_2, 0, data_2.length);
            
            
                                    String coboldata = new String(data_2);
            
                                    System.out.println("data from cobol : [" + coboldata + "]");
            
            
                                    // display return-code
                                    System.out.print("COBOL Return Code ");
                                    System.out.println(rc);
            
                                    // call the second test
                                    rc=subtest2.INSTANCE.cobsubtest2(pointer);
                                    System.out.print("COBOL Return Code ");
                                    System.out.println(rc);
            
                            } catch (UnsatisfiedLinkError e) {
                                    System.out.println("subtest Exception" + e);
                            }
                    }
            }
            
             
  • Simon Sobisch

    Simon Sobisch - 2016-01-18

    Thank you, very nice sample for the FAQ. It's likely worth to be put to https://sourceforge.net/p/open-cobol/contrib/HEAD/tree/trunk/samples/JAVA_using_COBOL

    BTW: I've added syntax highlighting to your posts via ::language and suggest you have a look at this via "Edit Post" :-)

     
    • Gary Cowell

      Gary Cowell - 2016-01-18

      I notice the syntax markers, thanks.

      I'm not really a JAVA programmer (I know it basically, but not steeped in it on a daily basis), I'm sure some will throw their hands up in horror, especially around the string handling and interfaces.

      I am wondering about compiling many .cbl files to a single .so though, as that would cut down the JNA glue. It might be fine for these small tests, but my full app has over 3,500 cobol modules.

       
      • Bill Woodger

        Bill Woodger - 2016-01-18

        Do all the 3,500 need to talk to JAVA? Even if so, what would be against a COBOL subprogram acting as an interface, the COBOL programs CALL that, it does the JAVA stuff, and returns from whence it came with whatever action completed and whatever result produced.

        Did you write all the COBOL programs yourself?

         
1 2 > >> (Page 1 of 2)

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.