What Z. wants to do:
make an existing C library accessible for PL/1 callers on the mainframe.
We did this sometimes in the past (when only old PL/1 compilers were available),
and our strategy was as follows (short description):
- first make sure that there is no signal handling inside the C function
package, because we like to do our own exception handling ... this is crucial
for our environment
- then: write C-PL/1 glue functions (or wrapper functions) that make the C API
functions accessible to PL/1 callers. The C interfaces presented to the PL/1
callers must obey the following rules:
a) only INTEGER function results, which can be mapped to PLIRETV; all other
function results have to be moved to additional result parameters
b) all by value parameters have to be passed by pointers, to support the default
"by reference" call of PL/1
c) for all parameters requiring descriptors (CHAR strings, structures, arrays),
do other parameter passing that involves no descriptors, for example passing
pointers and separate length information
The glue functions have to do the transformation of the PL/1 compatible
interface to the original interface of the C library.
This worked without problems for us in many cases. For example: we ordered a
stock exchange transaction calculation software (in C) and linked it to our
financial transaction system (written in PL/1). The third party, who wrote the
package, was not aware of the mainframe and of PL/1 ... they delivered the C
sources, which were for Unix/Windows originally ... we did the necessary
interfaces ourselves.
With the problem of NUL-terminated strings, you have to make a decision; either
PL/1 or C has to accept the logic of the other side. If the PL/1 side wants the
strings to be filled with blanks and have no NULL termination; C can cope with
this (but you have to take care, if you want to use some of ther str...
functions, anyway). If you want the strings to have nulls, you have some
troubles on the PL/1 side ... with old compilers, the new ones have CHAR (x)
VARZ, which is one of the nicest things if you have to deal with C functions
from PL/1 callers.
Kind regards
Bernd
Am 23.03.2014 21:44, schrieb S.H.:
> Z. -- these are some of the issues we face when we translate PL/I
> to any C-family language:
>
> o For an array passed as a function argument or received as a function
> parameter, PL/I must use a descriptor because the called function can ask
> the array's dimensions at run-time via the DIM(), LBND(), and HBND()
> BIFs.
>
> o An array is dynamically dimensioned if an upper or lower bound was passed
> as a function parameter. This requires that it be passed by descriptor
> so the called function can do the proper subscripting at run time.
>
> o A CONTROLLED variable is always represented by a descriptor because
> anyone (at any level of function call) can allocate a new instance
> (pushing previous ones down) or free the current instance (popping
> previous instances back up).
>
> o Regarding the NUL-terminated string issue, this is the old native
> vs. emulated question. If the called C code must deal with strings that
> are not NUL-terminated, then it can't use the str*() functions in the C
> RTL; it must have a special set instead. That makes the C code look a
> bit strange to the new C programmer who's just been hired.
>
> If you're interested, I can share what information we've found must be
> maintained in the various descriptors to make this work. Of course, we're in
> control of what gets generated by translation on both sides of a call, so we
> can do whatever we want that works; your C code is forced to accommodate what
> the PL/I compiler is generating.
>
> One thing you can do to alleviate a bit of pain is to have parallel PL/I and C
> include files that declare such things as array dimensions and string lengths,
> to avoid the trap of parallel maintenance. You could even do a script that
> would generate both from a common source, and make that a step in the build
> script.
>
> S.H.
>
|