- 1 Getting started
- 2 Compile
- 3 Customize
- 4 Optimize
- 5 Debug
- 6 Non-standard extensions
- 7 System Routines
- 附录 A
- 附录 B
- 附录 E
- 附录 I
2.3 C interface
This chapter describes how to combine C programs with COBOL programs.
2.3.1 Writing Main Program in C
Include libcob.h in your C program and call cob_init
before using any COBOL module. Do a cleanup afterwards, either by calling cob_stop_run
(if your program should terminate) or by calling cob_tidy
(if your program should execute further on without any more COBOL calls). Calling cob_init
, one or several GnuCOBOL modules and then cob_tidy
in this sequence can be done multiple times).
#include <libcob.h> int main (int argc, char **argv) { /* initialize your program */ ... /* initialize the COBOL run-time library */ cob_init (argc, argv); /* rest of your program */ ... /* Clean up and terminate - This does not return */ cob_stop_run (return_status); }
You can write cobc_init(0, NULL);
if you do not want to pass command line arguments to COBOL.
The easiest option to compile and/or link your C program is by passing the work to cobc
as follows:
cobc -x main.c
possibly running in verbose mode to see what cobc does:
cobc -x --verbose main.c # using -x -v or -xv would be also possible
or with several steps:
cobc -c main.c cobc -x main.o
As an alternative you can use the cob-config
tool to get the necessary options to be passed to the C compiler / linker.
cc -c `cob-config --cflags` main.c # compile only cc -o main main.o `cob-config --libs` # link only
2.3.2 Static linking with COBOL programs
Let’s call the following COBOL module from a C program:
---- say.cob --------------------------- IDENTIFICATION DIVISION. PROGRAM-ID. say. ENVIRONMENT DIVISION. DATA DIVISION. LINKAGE SECTION. 01 hello PIC X(7). 01 world PIC X(6). PROCEDURE DIVISION USING hello world. DISPLAY hello world. GOBACK. ----------------------------------------
This program accepts two arguments, displays them, and exits.
From the viewpoint of C, this is equivalent to a function having the following prototype:
extern int say(char *hello, char *world);
So, your main program will look like as follows:
---- hello.c --------------------------- #include <libcob.h> extern int say(char *hello, char *world); int main() { int ret; char hello[8] = "Hello, "; char world[7] = "world!"; /* initialize the COBOL run-time library */ cob_init(0, NULL); /* call the static module and store its return code */ ret = say(hello, world); /* shutdown the COBOL run-time library, keep program running */ (void)cob_tidy(); return ret; } ----------------------------------------
Compile and run these programs as follows:
$ cobc -x hello.c say.cob $ ./hello Hello, world!
or, more split and directly using the C compiler:
$ cc -c `cob-config --cflags` hello.c $ cobc -c -static say.cob $ cobc -x -o hello hello.o say.o $ ./hello Hello, world!
Note: The biggest benefits of static linking are that all programs are verified to be available in the resulting binary. Furthermore there is a slightly performance benefit in this type of CALL (not visible for "normal" programs).
2.3.3 Dynamic linking with COBOL programs
You can find a COBOL module having a specific name by using the C function cob_resolve
, which takes the module name as a string and returns a pointer to the module function.
cob_resolve
returns NULL
if there is no module. In this case, the function cob_resolve_error
returns the error message.
Let’s see an example:
---- hello-dynamic.c ------------------- #include <libcob.h> static int (*say)(char *hello, char *world); int main() { int ret; char hello[8] = "Hello, "; char world[7] = "world!"; /* initialize the COBOL run-time library */ cob_init(0, NULL); /* Find the module with PROGRAM-ID "say". */ say = cob_resolve("say"); /* If there is no such module, show error and exit. */ if(say == NULL) { fprintf(stderr, "%s\n", cob_resolve_error()); exit(1); } /* Call the module found ... */ ret = say(hello, world); /* ...and exit with the return code. */ cob_stop_run(ret); } ----------------------------------------
Compile and run these programs as follows:
$ cobc -x -o hello hello-dynamic.c $ cobc -m say.cob $ export COB_LIBRARY_PATH=. $ ./hello Hello, world!
The check of the module load as written above can be directly done in libcob as follows:
---- hello-dynamic2.c ------------------ #include <libcob.h> int main() { int ret; char hello[8] = "Hello, "; char world[7] = "world!"; void *cob_argv[2]; cob_argv[0] = hello; cob_argv[1] = world; /* initialize the COBOL run-time library */ cob_init(0, NULL); /* do a CALL, expecting the module to exist, otherwise exiting with an error. */ ret = cob_call ("say", 2, cob_argv); /* ...and exit with the return code. */ cob_stop_run(ret); } ----------------------------------------
In any case be aware that all errors that happen within COBOL will exit your program, as same as a STOP RUN
will do.
Depending on the application you possibly want to register C signal handlers; error and/or exit handlers in C and/or COBOL to do cleanups, logging or anything else.
There is one way to handle all these scenarios with a call, too, using cob_call_with_exception_check
instead of cob_call
as follows:
---- hello-dynamic3.c ------------------ #include <libcob.h> int main() { int ret; char hello[8] = "Hello, "; char world[7] = "world!"; void *cob_argv[2]; cob_argv[0] = hello; cob_argv[1] = world; /* initialize the COBOL run-time library */ cob_init(0, NULL); /* do a CALL, catching all possible results, */ ret = cob_call_with_exception_check ("say", 2, cob_argv); switch (ret) { case 0: /* program coming back */ /* Clean up and terminate runtime */ cob_runtime_hint("program exited with return code %d", cob_last_exit_code ()); cob_tidy (); break; case 1: /* normal exit */ cob_runtime_hint("STOP RUN with return code %d", cob_last_exit_code ()); break; case -1: /* error exit */ cob_runtime_hint("error exit with return code %d and error \"%s\"", cob_last_exit_code (), cob_last_runtime_error ()); break; case -2: /* hard error exit */ cob_runtime_hint("hard error exit with return code %d and error \"%s\"", cob_last_exit_code (), cob_last_runtime_error ()); break; case -3: /* signal handler exit */ cob_runtime_hint("signal handler exit with signal %d and error \"%s\"", cob_last_exit_code (), cob_last_runtime_error ()); break; default: cob_runtime_hint("unexpected return from cob_call_with_exception_check," " last exit code %d, last error \"%s\"", cob_last_exit_code (), cob_last_runtime_error ()); break; } /* ...and exit with zero if no error happened */ exit(ret != 0 && ret != 1); } ----------------------------------------
2.3.4 Static linking with C programs
Let’s call the following C function from COBOL:
---- say.c ----------------------------- int say(char *hello, char *world) { int i; for(i = 0; i < 7; i++) putchar(hello[i]); for(i = 0; i < 6; i++) putchar(world[i]); putchar('\n'); return 0; } ----------------------------------------
This program is equivalent to the program in say.cob above.
Note that, unlike C, the arguments passed from COBOL programs are not terminated by the null character (i.e., '\0'
).
You can call this function in the same way you call COBOL programs:
---- hello.cob ------------------------- IDENTIFICATION DIVISION. PROGRAM-ID. hello. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. 01 hello PIC X(7) VALUE "Hello, ". 01 world PIC X(6) VALUE "world!". PROCEDURE DIVISION. CALL "say" USING hello world. STOP RUN. ----------------------------------------
Compile these programs as follows:
$ cobc -x -o hello -static hello.cob say.c $ ./hello Hello, world!
or separate:
$ cc -c say.c $ cobc -c -static -x hello.cob $ cobc -x -o hello hello.o say.o $ ./hello Hello, world!
2.3.5 Dynamic linking with C programs
You can create a dynamically-linked module from a C program by compiling it with cobc ...
$ cobc -m say.c $ cobc -x hello.cob $ export COB_LIBRARY_PATH=. $ ./hello Hello, world!
or with most C compilers by passing option -shared
to the C compiler:
$ cc -shared -o say.so say.c $ cobc -x hello.cob $ export COB_LIBRARY_PATH=. $ ./hello Hello, world!
Mind that for COBOL to be able to load the module via CALL the name of the binary must either be identical to the CALL name or the binary containing the entry-point must have been loaded before (by a previous call or COB_PRE_LOAD).
2.3.6 Redirecting output to a (FILE *)
From a module written in C you can call cob_set_runtime_option
to set the exact (FILE *)
which is used to write trace data to. In common.h is the following:
enum cob_runtime_option_switch { COB_SET_RUNTIME_TRACE_FILE /* 'p' is FILE * */ COB_SET_RUNTIME_DISPLAY_PRINTER_FILE /* 'p' is FILE * */ COB_SET_RUNTIME_RESCAN_ENV /* rescan environment variables */ COB_SET_RUNTIME_DISPLAY_PUNCH_FILE /* 'p' is FILE * */ }; COB_EXPIMP void cob_set_runtime_option (enum cob_runtime_option_switch opt, void *p);
So from you C code you can tell the GnuCOBOL runtime to redirect TRACE output by:
cob_set_runtime_option (COB_SET_RUNTIME_TRACE_FILE, (void*)((FILE*)myfd));
You could also redirect all DISPLAY UPON PRINTER
output to a file by:
cob_set_runtime_option (COB_SET_RUNTIME_DISPLAY_PRINTER_FILE, (void*)((FILE*)myfd));
You could also redirect all DISPLAY UPON SYSPUNCH
output to a file by:
cob_set_runtime_option (COB_SET_RUNTIME_DISPLAY_PUNCH_FILE, (void*)((FILE*)myfd));
Another routine can be used to return the current value of the option.
COB_EXPIMP void * cob_get_runtime_option (enum cob_runtime_option_switch opt);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论