*> cobol-call-c-function.cob *> *> Calls three C functions from COBOL and shows the three parameter *> modes that matter at the C ABI boundary: BY VALUE for scalars C *> takes by value, BY REFERENCE for buffers C writes into, and *> RETURNING for a C return value. *> *> Source format: FIXED (the default). Targets GnuCOBOL 3.x. *> *> Build (the C side must be compiled first, then linked in): *> cc -c cobol-call-c-function.c *> cobc -x cobol-call-c-function.cob cobol-call-c-function.o *> ./cobol-call-c-function *> *> DESK-CHECKED against the GnuCOBOL Programmer's Guide and the *> GnuCOBOL FAQ. It has not been compiled here: no cobc on the *> machine this was written on. IDENTIFICATION DIVISION. PROGRAM-ID. CALLCDEMO. DATA DIVISION. WORKING-STORAGE SECTION. *> BINARY-LONG is a 32-bit signed integer and lines up with a C *> int32_t. BINARY-C-LONG exists precisely because C's own "long" *> is 32 bits on some platforms and 64 on others; use it only when *> the C side really did say "long". 01 WS-A USAGE BINARY-LONG VALUE 17. 01 WS-B USAGE BINARY-LONG VALUE 25. 01 WS-SUM USAGE BINARY-LONG VALUE 0. *> A buffer C writes into. COBOL will not null-terminate it for *> you, and C will not space-pad it for you, so the length is *> passed explicitly and the C side is told to stay inside it. 01 WS-BUFFER PIC X(32) VALUE SPACES. 01 WS-BUFFER-LEN USAGE BINARY-LONG VALUE 32. 01 WS-WRITTEN USAGE BINARY-LONG VALUE 0. *> A C string arriving as a pointer. POINTER plus a BASED item and *> SET ADDRESS OF is the idiom for reading memory C owns. 01 WS-CPTR USAGE POINTER. 01 WS-CCHAR PIC X BASED. 01 WS-NAME PIC X(32) VALUE SPACES. 01 WS-I USAGE BINARY-LONG VALUE 0. PROCEDURE DIVISION. MAIN-SECTION. *> 1. BY VALUE, with RETURNING for the result. *> int c_add(int a, int b); CALL "c_add" USING BY VALUE WS-A BY VALUE WS-B RETURNING WS-SUM END-CALL DISPLAY "c_add(" WS-A ", " WS-B ") = " WS-SUM *> 2. BY REFERENCE for a buffer C fills, BY VALUE for its length. *> int c_fill(char *buf, int len); *> The return value says how many bytes it wrote. CALL "c_fill" USING BY REFERENCE WS-BUFFER BY VALUE WS-BUFFER-LEN RETURNING WS-WRITTEN END-CALL DISPLAY "c_fill wrote " WS-WRITTEN " bytes: " WS-BUFFER(1:WS-WRITTEN) *> 3. A C function that returns a char *. Take it into a POINTER, *> then walk it a byte at a time until the null. COBOL has no *> null-terminated string type, so the walk is the conversion. CALL "c_name" RETURNING WS-CPTR END-CALL MOVE SPACES TO WS-NAME MOVE 0 TO WS-I PERFORM UNTIL WS-I >= 32 SET ADDRESS OF WS-CCHAR TO WS-CPTR IF WS-CCHAR = X"00" EXIT PERFORM END-IF ADD 1 TO WS-I MOVE WS-CCHAR TO WS-NAME(WS-I:1) SET WS-CPTR UP BY 1 END-PERFORM DISPLAY "c_name returned: " WS-NAME(1:WS-I) STOP RUN. END PROGRAM CALLCDEMO.