Search code examples
ccobolgnucobol

Getting a 64 bit return value from a C function in GNU COBOL


I need to call a function written in C from a GNU COBOL program which returns a 64 bit integer (BINARY-DOUBLE in COBOL). However, it seems like GNU COBOL assumes that the return value is always BINARY-LONG, which means the return value is messed up.

Of course, the obvious solution would be to "return" the value by passing a reference to where I want the C function to put it, but I can't change the original C function. I could write a wrapper in C, but it seems annoying to do that every time I need call a function with a 64-bit return value, so I'm wondering if there's a way to do this within COBOL.


Solution

  • Of course, I figured it out immediately after posting. The solution is just to store the return value in a pointer. Using REDEFINES, we can make a pointer that overlaps our 64-bit integer. In effect, this is basically the same thing as returning directly into the integer. Example:

    ext.c:

    #include <stdint.h>
    
    uint64_t testfun() {
        return 0x1213141516171819;
    }
    

    main.cob:

           IDENTIFICATION DIVISION.
           PROGRAM-ID. main-prog.
           DATA DIVISION.
           WORKING-STORAGE SECTION.
           01 retint USAGE BINARY-DOUBLE UNSIGNED.
           01 retval REDEFINES retint USAGE POINTER.
           PROCEDURE DIVISION.
               CALL STATIC "testfun" RETURNING retval.
               DISPLAY "retval: " retval.
               DISPLAY "retint: " retint.
               STOP RUN.
    

    Edit: I should probably clarify, this only works on ABIs where pointers and 64-bit integers have the same representation.