Operating System - OpenVMS
1752742 Members
5198 Online
108789 Solutions
New Discussion юеВ

Re: Sending a "file pointer" from COBOL to a C subroutine...

 
SOLVED
Go to solution
Kevin Hardy
Occasional Advisor

Sending a "file pointer" from COBOL to a C subroutine...

We have a COBOL program that does extensive RMS file operations and writes the results to a print file. We want to combine this program with an existing C subroutine that would write output to this same print file. However, I can't find a way from COBOL to obtain the C-style file pointer to pass to this subroutine. Is this even possible?

Thanks in advance.
10 REPLIES 10
Robert Gezelter
Honored Contributor

Re: Sending a "file pointer" from COBOL to a C subroutine...

Kevin,

In short, offhand I do not recall a supported way to do this.

If the file must be written from both C and COBOL, I would write a subroutine (which can be called from both environments, as well as any other conforming language), that writes strings to the file.

Alternatively, if you have access to the RMS pointers, you can just invoke the RMS routines directly from your C code. In that case, you will need to use -sprint- etc. to format the data into strings (and then pass the actual string and string length to RMS).

- Bob Gezelter, http://www.rlgsc.com
Hein van den Heuvel
Honored Contributor

Re: Sending a "file pointer" from COBOL to a C subroutine...

Sure, just call the support interface DCOB$RMS_CURRENT_RAB after a cobol print and stash it away, passing it to C when needed.

Mind you, another OpenVMS way to do this is to create a PROCESS PERMANENT FILE, by opening it up in the process BEFORE starting the image. Now you can have multiple openers from the image share the same buffers.

Remember, google is your friend.
As is the Cobol documentation.

hth,
Hein.

Hein van den Heuvel
Honored Contributor

Re: Sending a "file pointer" from COBOL to a C subroutine...


I may have read too quickly.
You don't just want to print to the same file from C, you want to use the C-io with file handles and such.

Ah, that's going to be harder (without the process permanent file).

Please consider using 'sprintf' and sys$put (cobol-provided-rab)

Be sure to save the rbf and rsz when coming from cobol, and restore it before before going back. So you really want a small wrapper arounf sys$put passing the rab, and the c record buffer.

Hein.


Richard J Maher
Trusted Contributor

Re: Sending a "file pointer" from COBOL to a C subroutine...

Hi Kevin,

(As well as what Hein said) Does C have a way of declaring a file to be EXTERNAL? In other words, a global stream to a file that doesn't have to be passed as a formal parameter yet can be mapped in a subroutine as something that was OPENed in a mainline?

COBOL does, but IIRC this used to be done with overlaying PSECTs but changed for Alpha. (We used to get the address of RMS-STS OF filename and then get the FAB/RAB from that, but on Alpha we have the DCOB$ routines. )Not having my Alpha powered-up to do a COB/MACHINE_CODE I imagine that some Common Language Run-time calling-standard says you "should" be able to map a FAB somewhere?

Anyone know the C syntax for declaring a file/stream as EXTERNAL?

Cheers Richard Maher
Dennis Handly
Acclaimed Contributor

Re: Sending a "file pointer" from COBOL to a C subroutine...

>Richard: Does C have a way of declaring a file to be EXTERNAL?

An extern FILE* in C isn't likely to match what COBOL has. At least not under HP-UX or MPE/iX.
John Gillings
Honored Contributor
Solution

Re: Sending a "file pointer" from COBOL to a C subroutine...

Kevin,
Stepping back to explain the issue...

"File objects" in whatever language are a construct of the language RTL. Both C and COBOL have their own ideas about what a "file" is, how it behaves, and what the language value-adds to the underlying operating system primitives (in this case, mostly provided by RMS, but not necessarily). For example, both COBOL and C may implement some kind of caching or record buffering above the operating system (RMS) level.

The trouble is, the language specific layers are opaque, so there's no supported way to reconcile any inconsistencies between the language models, or do necessary things like flushing caches.

Applying Hext's rule "All problems can be solved with the addition of a further level of indirection", you can build your own application layer in one of the languages and call that to interact with your shared file. This has the benefit of generalising the issue. You can have your own "file pointer" object and apply the same solution to multiple files.

Another possibility is to have each language open the file independently as read/write shared, just as if the two sets of routines in different languages were in different processes. RMS doesn't care, but this is more expensive than the common module approach as you have duplicate sets of data structures, and your process needs to synchronize against itself. The benefit here is if you have lots of existing code, you may only need to tweak the OPEN statement to change it into shared access (but check for interdependent records that might get records from the other accessor interleaved).
A crucible of informative mistakes
Richard J Maher
Trusted Contributor

Re: Sending a "file pointer" from COBOL to a C subroutine...

Hi Denis,

No idea what happens on HP/UX or MPE/iX (Whatever that may be :-) but could you please tell me what "extern FILE*" becomes after compilation and I may have another option.

For example, if it becomes an Integer Pointer in an separate overlayable and global PSECT that contains the address of the file's FAB then it would be easy to create such a pointer in COBOL and populate it with the DCOB$get_fab_thing address.

Hi John,

Something in the back of my mind about COBOL's use of RMS' Internal Stream Identifiers makes me think opening the file twice does not does not render the same environment as two processess opening the same file, but I could be wrong :-)

Hi Hein,

OTY

Cheers Richard Maher
Hein van den Heuvel
Honored Contributor

Re: Sending a "file pointer" from COBOL to a C subroutine...

Richard>> please tell me what "extern FILE*" becomes after compilation and I may have another option. For example, if it becomes an Integer Pointer in an separate overlayable and global PSECT that contains the address of the file's FAB

For standard C IO the C RTL has its own file descriptor describing pretty much a 'buffer' with a current byte position. And yeah there are pointers to a rab and fab as well to perform a sys$write ... eventually. It does not really use RMS, other than the thin convenience layer $READ and $WRITE provide over SYS$QIO. Main reason for that is the single byte IO too many C appliations use too often. The RMS API, probing, CMEXEC and such is just too intense for simple byte IO.
With ctx=rec, the C-rtl will use RMS in record mode (SYS$PUT, SYS$GET) and it will happily report the fab/rab, but takes unkindly to manipulating those.

Check out $HELP CRTL CREAT ARG
(no final E on create, look of 'acc')

Hmmm.. I suppose that in the error callback you could close the C file, and stuff the IFI/ISI words from the cobol FAB/RAB into the C-rtl provide rabs/fabs, making them be the Cobol rabs/fabs as far as RMS is concerned.

Richard>> Something in the back of my mind about COBOL's use of RMS' Internal Stream Identifiers makes me think opening the file twice does not does not render the same environment as two processess opening the same file, but I could be wrong :-)

Opening the same file twice from a single process, using two FABs/RABs is undistinguishable from them being opened from different processes... unless the filespec used is a LOGICAL name for a PROCESS PERMANENT file (with the isi hiding (escaped) in the logical name translation.)


Hi Hein,
OTY
Cheers Richard Maher

"Excuse me? Are you looking at me? Did you rub my lamp? Did you wake me up, did you bring me here? And all of a sudden, you're walkin' out on me? I don't think so, not right now! You're getting your wishes, so sit down! "

Hein.


Richard J Maher
Trusted Contributor

Re: Sending a "file pointer" from COBOL to a C subroutine...

Hi Hein,

>>>>>>>>>>>>>>>>>
Opening the same file twice from a single process, using two FABs/RABs is undistinguishable from them being opened from different processes...
<<<<<<<<<<<<<<<<<

But that's just it; something (again faint recollection) tells me that COBOL could produce multiple RABs per FAB (or something like that) Multiple $connects/fab?

Anyway 1 IFI per > 1 ISI which (again IIRC) could lead to dodgy "Invalid Internal Stream Identifier" errors if one stream was closed and you tried to access the other one. (Maybe also Key of Reference and Locking issues?) But as none of this seems relevant, I'll stop babbling about it.

@Kevin,

Ok, my final offer (given single byte I/O Yuk!) is still to declare the print-file as external in the COBOL mainline, tehn call the C code and when you need to output from C to the report file just call another COBOL subroutine that also maps the file as EXTERNAL and does the I/O.

Cheers Richard Maher

PS. Speaking of final offers; I just bought a brand new Kia Grand Carnival Premium $48K flat drive away with all the fruit! It's as glammerous as the Wagon Queen Family Truckster but hey it's practical :-)