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.
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.