|
From: | Michael Anderson |
Subject: | Re: [open-cobol-list] user generated final bindings, more day dreaming |
Date: | Sun, 30 Jun 2013 14:34:52 -0500 |
User-agent: | Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20130623 Thunderbird/17.0.7 |
On 06/30/2013 09:22 AM, Patrick wrote:
Hi Everyone It's not that hard, I think you're making it harder than it really is. Follow me here, a not so quick example to show that asking Cobol to pass data to C, is not so difficult. Move 0 To wsEvents-status. Move 2.0 To wsEvents-seconds. Perform Wait-for-Events. So, in the paragraph “Wait-for-Events”: Call "wsEvents" Using wsEvents-seconds Giving wsEvents-status. Move wsEvents-status To WebSocket-Wait-Status. Evaluate True *> for logging only When WebSocket-Timeout Move "WebSocket TIMEOUT" to logmsg Perform write-logmsg When Browser-Sent-Data Move "WebSocket Ready To Read" to logmsg Perform write-logmsg When other Move "WebSocket State is unknown" to logmsg Perform write-logmsg End-Evaluate. To explain “wsEvents”, it is one of many C functions that I wrote, and linked into my OpenCobol program, and it gives my Cobol application a time-out on stdin. There maybe an easier way to have a time-out on an accept from stdin, but that's not my point here. The point is “bindings”, specifically, binding of variables, and linking the correct Cobol datatype to the correct C datatype. wsEvents It looks like so: /**************** wsEvents *******************/ int wsEvents (ev_tstamp *seconds) { LogDebug("wsEvents: begins with a %5.3f second timeOut", *seconds); struct ev_loop *loop = ev_default_loop (0); ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ); ev_io_start (loop, &stdin_watcher); ev_timer_init (&timeout_watcher, timeout_cb, *seconds, 0.); ev_timer_start (loop, &timeout_watcher); ev_loop (loop, 0); ev_io_stop (EV_A_ &stdin_watcher); ev_timer_stop (EV_A_ &timeout_watcher); LogDebug("wsEvents: Ends EVENT_STATUS = %d", EVENT_STATUS); return EVENT_STATUS; } In C we can just invent our own datatype using typedef! So, from within Cobol, What the heck is the C datatype "ev_tstamp"? I can guess that it is a number of seconds, I would think it could be of type int. The only way to be sure is to find the 'ev_tstamp' typedef in ev.h header file, where is was invented/defined. What do I find: typedef double ev_tstamp; It turns out to be a double, which I know is a 8 byte float, so what is that in Cobol? 1 wsEvents-seconds Usage is COMPUTATIONAL-2. Similarly: ev_tstamp could have turned out to be a struct of some kind or whatever, but it was just a double..... another example using a struct. A rather large struct in C, something else I used to create a library "vuelib" in C, callable by Cobol: struct vcom { short cstatus; short language; short comarealen; short userbuflen; short cmode; short lastkey; short numerrs; short windowenh; short multiusage; short labeloption; UCHAR cfname[16]; UCHAR nfname[16]; short repeatapp; short freezapp; short cfnumlines; short dbuflen; short filler0; short lookahead; short deleteflag; short showcontrol; short filler1; short printfilnum; short filerrnum; short errfilenum; short formstoresize; short filler2; short filler3; short filler4; int numrecs; int recnum; short filler5; short filler6; short filen; short filler7; short filler8; short filler9; short filler10; short filler11; short retries; short termoptions; short environ; short usertime; short identifier; short labinfo; }; // Now define a new datatype called vcom_t typedef struct vcom vcom_t; The same struct defined in Cobol would be: 01 COMAREA. 03 CSTATUS PIC S9(4) COMP. 88 GOOD-CALL VALUE 0. 88 TIME-OUT VALUE 160. 88 NO-VIEW-ERROR VALUE 0. 03 LANGUAGE PIC S9(4) COMP. 03 COMAREALEN PIC S9(4) COMP. 03 USERBUFLEN PIC S9(4) COMP. 03 CMODE PIC S9(4) COMP. 03 LASTKEY PIC S9(4) COMP. 03 NUMERRS PIC S9(4) COMP. 03 WINDOWENH PIC XX. 03 FILLER REDEFINES WINDOWENH. 10 FILLER PIC X. 10 V-ENHANCE PIC X. 03 MULTIUSAGE PIC S9(4) COMP. 03 LABELOPTIONS PIC S9(4) COMP. 03 CFNAME PIC X(16). 03 NFNAME PIC X(16). 03 REPEATAPP PIC S9(4) COMP. 03 FREEZEAPP PIC S9(4) COMP. 03 CFNUMLINES PIC S9(4) COMP. 03 DBUFLEN PIC S9(4) COMP. 03 FILLER PIC S9(4) COMP. 03 LOOKAHEAD PIC S9(4) COMP. 03 DELETEFLAG PIC S9(4) COMP. 03 SHOWCONTROL PIC S9(4) COMP. 03 FILLER PIC S9(4) COMP. 03 PRINTFILNUM PIC S9(4) COMP. 03 FILERRNUM PIC S9(4) COMP. 88 NO-FILE-ERROR VALUE 0. 03 ERRFILENUM PIC S9(4) COMP. 03 FORMSTORESIZE PIC S9(4) COMP. 03 FILLER PIC S9(4) COMP OCCURS 3. 03 NUMRECS PIC S9(6) COMP. 03 RECNUM PIC S9(6) COMP. 03 FILLER PIC S9(4) COMP OCCURS 2. 03 FILEN PIC S9(4) COMP. 03 FILLER PIC S9(4) COMP OCCURS 5. 03 RETRIES PIC S9(4) COMP. 03 TERMOPTIONS PIC S9(4) COMP. 03 AUTOREAD-OPTION REDEFINES TERMOPTIONS PIC S9(4) COMP . 03 ENVIRON PIC S9(4) COMP. 03 USERTIME PIC S9(4) COMP. 03 IDENTIFIER PIC S9(4) COMP. 03 LABINFO PIC S9(4) COMP. Passing vcom_t data from Cobol to C: MOVE LOW-VALUES TO COMAREA. MOVE ZERO TO LANGUAGE. MOVE 60 TO COMAREALEN. MOVE 1 TO LABELOPTIONS. MOVE ZERO TO LOOKAHEAD. MOVE 4 TO FORMSTORESIZE. MOVE SPACES TO FILENAME. string "QCSFORM.QC.SOURCE" delimited by size inTO FILENAME. move "testform" to NFNAME. CALL "VOPENFORMF" USING COMAREA FILENAME. IF CSTATUS OF COMAREA NOT = 0 MOVE "Y" TO STOP-NOW Call "VSHOWERRMSG" Using COMAREA. What does this look like from the C side: NOTE: that CALL "VOPENFORMF" USING COMAREA FILENAME. will (by default) only pass the memory addresses of COMAREA and FILENAME. Same as: CALL "VOPENFORMF" USING By Reference COMAREA By Reference FILENAME. So, in the C code we use * to say this a memory address pointer. void VOPENFORMF(vcom_t *comarea, UCHAR *VopenFile); Then from the C side you can reference these items like so: fprintf (stdout, "DEBUG: VOPENFORMF language : %d \n", comarea->language); fprintf (stdout, "DEBUG: VOPENFORMF comarealen : %d \n", comarea->comarealen); fprintf (stdout, "DEBUG: VOPENFORMF labeloptions : %d \n", comarea->labeloption); fprintf (stdout, "DEBUG: VOPENFORMF lookahead : %d \n", comarea->lookahead); fprintf (stdout, "DEBUG: VOPENFORMF formstoresize : %d \n", comarea->formstoresize); fprintf (stdout, "DEBUG: VOPENFORMF nfname : %s \n", comarea->nfname); So, not much marshalling to do here, just passing addresses and such..... I've done similar stuff with AcuCobol, fujitsu, and others, works with minimal confusion. However, what makes OpenCobol so good with this, is that they (OC and Cobol) are using the same compiler, which is just too cool! The philosophy here is "Application Programming vs Systems Programming". Where Cobol is a application programming language, there are things that I do not want coded in my application, like wsEvents. I could make all the calls to (ev_io_init, ev_io_start) directly from OpenCobol, but it is better not to clutter up my application with such things. You can't find a better language for business applications than Cobol, likewise, you can't find a better Systems programming language than C (not to be confused with C++ or C#). I can't begin to THANK all the OC developers enough for giving us one compiler for both languages, OC is the best! Thank You OC developers! -- Mike. PS: think of enumerations as Cobol 88 level bools. And COBOL Function Length combined with C sizeof will also help you understand various data types. |
[Prev in Thread] | Current Thread | [Next in Thread] |