On 9/16/2010 11:38 AM, Scott Ford wrote:
I have seen several 'bit and piece' posts on LE Cobol calling C
All:
I have seen several 'bit and piece' posts on LE Cobol calling C. I have written
a sample C call and here is the source and have included the C source and JCL ,
Cobol source and JCL, I dont understand what I have missed, I have been through
the LE Books and C-C++ books and I am confused and the execution is receiving a
S0C7 :
JCL for 'C' compile:
----------------------
//ADCDMETA JOB SYSTEMS,MSGLEVEL=(1,1),MSGCLASS=X,CLASS=A,PRTY=8,
// NOTIFY=&SYSUID,REGION=0M
// EXEC EDCCL,
// INFILE=SFORD.JCLLIB.CNTL(TESTC)',
// OUTFILE='SFORD.CLINKLIB(TS04B),DISP=SHR'
'C' Source:
-------------------
#include<stdio.h>
#include<string.h>
#pragma linkage(TS04B,COBOL)
void TS04B( char *pBuffer )
{
strcpy( pBuffer, "OK ");
fprintf(stderr,"ok trans\n");
}
LE Cobol V4r1 JCL:
--------------------------
//ADCDTHRA JOB SYSTEMS,MSGLEVEL=(1,1),MSGCLASS=X,CLASS=A,PRTY=8,
// NOTIFY=&SYSUID,REGION=4096K
//*----------------------------------------------------------------
//COB EXEC PGM=IGYCRCTL,
// PARM=('NOC(E)','FLAG(W)','DATA(31)',NODYN,RES,RENT,OPT,
// MAP,NOSSR,NOZWB,NUM,NOTERM,NOVBREF,X,APOST,LIB,LIST),
// REGION=1024K
//STEPLIB DD DISP=SHR,DSN=IGY410.SIGYCOMP
//SYSLIB DD DISP=SHR,DSN=CEE.ACEESRC1
// DD DISP=SHR,DSN=SFORD.CLINKLIB
//SYSPRINT DD SYSOUT=X
//SYSUT1 DD UNIT=VIO
//SYSUT2 DD UNIT=VIO
//SYSUT3 DD UNIT=VIO
//SYSUT4 DD UNIT=VIO
//SYSUT5 DD UNIT=VIO
//SYSUT6 DD UNIT=VIO
//SYSUT7 DD UNIT=VIO
//SYSLIN DD DISP=(,PASS),DSN=&&LOADSET,
// UNIT=VIO,
// DCB=BLKSIZE=3200
//SYSIN DD DISP=SHR,DSN=SFORD.COBOL.SOURCE(THRALLC)
//*
//LNK EXEC PGM=IEWL,
// COND=(4,LT,COB),
// PARM='LIST,XREF',
// REGION=4096K
//SYSLIB DD DISP=SHR,DSN=SFORD.CLINKLIB
// DD DISP=SHR,DSN=CEE.SCEELKED
// DD DISP=SHR,DSN=SYS1.CSSLIB
// DD DISP=SHR,DSN=TCPIP.SEZATCP
//SYSLMOD DD DISP=SHR,DSN=SFORD.CLINKLIB
//SYSUT1 DD UNIT=SYSDA,
// DCB=BLKSIZE=1024,
// SPACE=(1024,(200,20))
//SYSPRINT DD SYSOUT=X
//SYSLOUT DD SYSOUT=X
//SYSLIN DD DISP=(OLD,DELETE),DSN=&&LOADSET
// DD DDNAME=SYSIN
//SYSIN DD *
MODE AMODE(31),RMODE(ANY)
INCLUDE SYSLIB(EDCSTART)
INCLUDE SYSLIB(CEEROOTB)
INCLUDE SYSLIB(@@CBL2C)
INCLUDE SYSLMOD(TS04B)
ENTRY THRALLC
NAME THRALLC(R)
/*
//
LE Cobol Source:
---------------------
IDENTIFICATION DIVISION.
PROGRAM-ID. THRALLC.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
DATA DIVISION.
FILE SECTION.
WORKING-STORAGE SECTION.
01 TS04B PIC X(8) VALUE 'TS04B'.
01 TESTIT PIC X(10) VALUE 'SCOTT'.
PROCEDURE DIVISION.
DISPLAY 'START OF TS04A'.
CALL TS04B USING TESTIT.
DISPLAY TESTIT.
GOBACK.
Sorry for the long post, but I think one has to see all the pieces.
Please tell me am I blind in my old age or what...
Thanks in advance.
Scott J Ford
I think there's a bunch of issues here, so I'll try and address
them all.
1. It seems to me you unnecessarily complicate things by
calling your C source member TESTC and then binding it
under the name TSO4B; why do that? life is simpler if
you can use source member names the same as load module
names; so I reverted to that
2. You don't really need the #pragma linkage(TS04B,COBOL)
or, in my case, #pragma linkage(TESTC,COBOL) statement;
(we'll see the tradeoffs shortly)
3. When you pass an array (in this case, a character string)
to a C subroutine, C expects to be passed a pointer to
the string; C also does not handle the end-of-list bit
flag that COBOL generates; there are three ways (at least)
to handle this:
* code the #pragma linkage(TESTC,COBOL) statement
- don't like to limit a subroutine to a single
programming language
* in your calling program, pass an extra parm, so that
the first parm is the true string you want to pass
and the second parm is just a place for COBOL to
set on the end-of-list flag, which C will not even
notice, since it is only expecting one parameter
- a simple example, that works, is to name the
parameter twice, such as:
call testc using testit, testit
(this works)
* in your calling program, set up pointer to your
last (and only, in this case) argument, and pass
the pointer BY VALUE; for example:
IDENTIFICATION DIVISION.
PROGRAM-ID. THRALLC.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 TS04B PIC X(8) VALUE 'TESTC'.
01 TESTIT PIC X(10) VALUE 'SCOTT'.
01 TESTIT-PTR POINTER.
PROCEDURE DIVISION.
DISPLAY 'START OF THRALL.'
SET TESTIT-PTR TO ADDRESS OF TESTIT
CALL 'TESTC' USING BY VALUE TESTIT-PTR
DISPLAY TESTIT
GOBACK.
(this, too, works)
3. I notice you compiled with NODYNAM, but you made
a dynamic call (CALL data-item is _always_
dynamic, since the compiler can't tell what will
be in 'data-item' at run time, so it can't tell
the binder to include the subroutine); in the
spirit of your code, I coded CALL 'routine' but
compiled with NODYNAM, which will create a static
call
4. All was almost all well, until I kept getting a
return code of 9; some investigation shows the
return value of fprintf, printf, and sprintf is
the number of characters printed; this value is
sent back to the calling program; I fixed this
by adding a return(0) in the subroutine; but
the compiler was unhappy because the type of
the function could not then be 'void'; so I
changed it to 'int' and all was well
5. I did not need _ANY_ binder (linkage editor) control
statements; the default processes work fine
So, compile member TESTC into load module member TESTC:
#include <stdio.h>
#include <string.h>
int TESTC( char *pBuffer )
{
strcpy( pBuffer, "OK");
fprintf(stderr,"ok trans\n");
return(0);
}
[Not quite sure why you used fprintf instead of printf,
but either works]
Then compile member THRALLC into load module THRALLC:
PROCESS OFFSET NODYNAM
IDENTIFICATION DIVISION.
PROGRAM-ID. THRALLC.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 TS04B PIC X(8) VALUE 'TESTC'.
01 TESTIT PIC X(10) VALUE 'SCOTT'.
01 TESTIT-PTR POINTER.
PROCEDURE DIVISION.
DISPLAY 'START OF THRALL.'
SET TESTIT-PTR TO ADDRESS OF TESTIT
CALL 'TESTC' USING BY VALUE TESTIT-PTR
DISPLAY TESTIT
GOBACK.
the binder will automatically pick up TESTC; Then run
and the result was:
START OF THRALL.
ok trans
OK TT
Not sure what you were trying to do, but that's what
your code does.
<ad>
All this, and lots more, is covered in our 3 and a
half day course "Secrets of Inter-Language Communication
in z/OS". Details at:
http://www.trainersfriend.com/Language_Environment_courses/m520descr.htm
</ad>
--
Kind regards,
-Steve Comstock
The Trainer's Friend, Inc.
303-393-8716
http://www.trainersfriend.com
* To get a good Return on your Investment, first make an investment!
+ Training your people is an excellent investment
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to [email protected] with the message: GET IBM-MAIN INFO
Search the archives at http://bama.ua.edu/archives/ibm-main.html