On 9/08/2016 12:36 AM, Farley, Peter x23353 wrote:
> David,
>
> Not so easy to write as you might think. The COBOL LE environment and the C/C++ LE environment are very different. Calling C/C++ runtime routines (other than the Metal C ones resident in the system, but even some of those require some memory-allocation initialization) requires that the C/C++ RTL environment be set up, but you do not want to do that for every call, so you have to have at least a name/token pair to save the (created once) C/C++ environment.
#pragma linkage(...,fetchable) takes care of the ILC linkage. LE will
dynamically load the C++ module and use the same LE environment for both
the COBOL and the C++ program. I've done this before for ILC calls
between HLASM->C++ and it works well. It's very fast, the call overhead
is just a few instructions in the FECB glue code.
I wrote a test with a COBOL main that calls a C++ subroutine 10,000,000
times. It ran in 01.33 CPU seconds, roughly the same as C++ calling a
statically linked C++ routine.
identification division.
program-id. cobilc.
data division.
working-storage section.
01 set-module-name pic x(08) value "PCOLSET ".
procedure division.
perform 10000000 times
call set-module-name
end-perform
goback.
#pragma linkage(PCOLSET,fetchable)
extern "C" int PCOLSET()
{
return 0;
}
HTRT01I CPU (Total) Elapsed
CPU (TCB) CPU (SRB) Service
HTRT02I Jobname Stepname ProcStep RC I/O hh:mm:
ss.th hh:mm:
ss.th
hh:mm:
ss.th hh:mm:
ss.th Units
HTRT03I COBILC C 00 73 01.33 02.24
01.33 00.00 29549
> And probably impossible for any RTL routine that requires POSIX ON, though I don't suppose the data collection routines fall into that category.
One of my colleagues wrote a POSIX(ON) COBOL program a few weeks ago. It
uses the new callable services for HTTP web services and POSIX(ON) is a
requirement. No problems.
> I investigated this once upon a time and decided that with the amount of work required, it would probably be better to wait for IBM to provide it. Maybe COBOL V6++ will do that. :)
From what I can tell it would be quite easy. It's simple to write a C++
module to wrap an STL container. I would design it to take one argument,
a COBOL record (C struct) list with a request type, the set handle and a
record buffer. For example, for a dictionary (std::set) NEW, TERM,
INSERT, FIND, REPLACE, DELETE etc. I would store records in the set as
C++ strings to simplify memory management and write a custom comparator
function for comparing keys. One constraint would be that record keys
must be fixed length, but this is COBOL right so that's nothing new.
Excuse my COBOL, it's been a while but something like this which would
have a C/C++ structure mapping in the API.
01 stl-set.
05 stl-set-token pic x(4) value low-values.
05 stl-set-method pic x.
88 stl-set-method-new value 'N'.
88 stl-set-method-insert value 'I'.
88 stl-set-method-find value 'F'.
88 stl-set-method-update value 'U'.
88 stl-set-method-delete value 'D'.
88 stl-set-method-term value 'T'.
05 stl-set-key-length pic 9(8) binary.
05 stl-set-rec-length pic 9(8) binary.
05 stl-set-rec-ptr pointer.
struct stl_set
{
void * token; // ptr to std::set instance
enum // request type
{
method_new = 'N', // - create a new set
method_insert = 'I', // - insert a record
method_find = 'F', // - find a record
method_update = 'U', // - update a record
method_delete = 'D', // - delete a record
method_term = 'T' // - destroy the set
} method;
size_t keylen; // [input] the fixed key length
size_t reclen; // [in/out] the record length
void * rec; // [in/out] the record buffer