Environment is 64-bit AIX, Visual COBOL 2.1 but compiling on the command line.
I have a simple COBOL program calling a simple C program. The COBOL program is compiled as 64-bit. The C program is, as far as I am aware, compiled as 64-bit - I have used the compilation option -maix64 and the loader option -b64. Running the program generates the error "253 Cannot load file - unsupported format". I have also tried compiling the COBOL program as 32-bit but with the same result. A previous question in the forum about this same result was apparently due to a 64-bit COBOL program calling a 32-bit C program, but I think I've eliminated that.
To eliminate anything else, I edited the two programs down to absolute basics (the return 19 in the C program is so I can check that a value is definitely being returned):
program-id. testc.
special-names.
call-convention 0 is aix-c.
working-storage section.
01 ws-name pic x(4) value "fred".
01 ws-return-val pic s9(9) comp-5.
procedure division.
a-control section.
move zero to ws-return-val
call aix-c "helloworld" using ws-name
returning ws-return-val
display "Returned " ws-return-val
goback
.
#include <stdio.h>
int
main( int argc, char **argv )
{
printf( "Hello %s\\n", argv[1] );
return( 19 );
}
So have I missed something blindingly obvious?
Hi
just copy the below into doit.sh on the AIX machine.
In a temporary directory
make sure cobsetenv has been run
. ./doit
>>>>>>> doit.sh
JAVA_HOME=/usr/java6
export JAVA_HOME
PATH=$HOME/bin:$JAVA_HOME/bin:/sbin:/usr/sbin:$PATH
export PATH
LANG=en_US
export LANG
TERM=vt220
export TERM
#
java -version
#
COBMODE=32
export COBMODE
#
#. /home/products/vcdevhub22/bin/cobsetenv
#
#
cat >testc.cbl <<EOF
program-id. testc.
working-storage section.
01 ws-name pic x(5) value "fred" & x'00'.
01 ws-return-val pic s9(9) comp-5.
procedure division.
a-control section.
move zero to ws-return-val
call "helloworld" using ws-name
returning ws-return-val
display "Returned " ws-return-val
goback
.
EOF
#
# the c program
#
cat >helloworld.c <<EOF
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
int helloworld(char *dptr_char)
{
printf("In C helloworld\\n");
int result = 0;
if(strcmp(dptr_char, "abcdefghijklmnopqrst") == 0)
{
printf("char * passed correctly <%s>\\n", dptr_char);
}
else
{
printf("char * failed <%s>\\n", dptr_char);
result = result 1000;
}
return(result);
}
EOF
#
# compile and link
#
cob -xvV testc.cbl helloworld.c
#
./testc
#
# end
#
>>>>>>>>> end doit.sh
Some extra stuff
Notes
I attach some c examples interfacing with cobol which might help you?
when I mix C and COBOL development I use CDT eclipse plugin this does not do remote development.
Then just new > select wizard C/C convert to a C/C project (adds C nature)
This will find libraries.
I use cygwin on windows or mingw to give me access to the c header files and gcc.
Not brilliant but a start for the IDE to work, but the compile is actually done on the AIX machine and uses theheader files on the unix machine.
I use the cobol compiler on the AIX machine to compile the c code.
I would compile the c files by adding them to the additional link files.
This would then get them compiled via the cob command.
Some examples come with the product
/home/products/vcdevhub22/demo/cobol/c-cobol >ls
ccob1.sh cmain1.h cobfunc1.cbl cobsub1.cbl csub1.c cxxcob1.sh cxxsub1.C
cmain1.c cobc1.sh cobmain1.cbl cobsub2.cbl ctypes.cpy cxxmain1.C README.txt
If you wanted just c programs built into your application do
Properties>Micro focus COBOL> Build configurations>link>additional link items
And add the *.c programs here.
The examples above in the product need to be libraries so I would do this to make libraries.
Properties>Micro focus COBOL>Build configurations>events>
Use the pre build command event line.
cob -z,CC -v cxxsub1.C -e ""
cob -zv csub1.c
exit 0
you can stop the build here by using exit 1.
Here is a simple example of c calling cobol and cobol calling c
Create your remote project.
Ccallcobolcallc
Cut and paste the 3 files below.
Add the c files to the additional link files
Properties>Micro focus COBOL>COBOL>
set your entry point to
main
Clean build.
>>>>>>>>>>>>>>>
*> This sets the 2 byte return code from c
$set rtncode-size"2"
program-id. acceptingfromc as "acceptingfromc".
environment division.
configuration section.
data division.
working-storage section.
01 int pic s9(9) comp-5 is typedef.
$IF P64 set
77 long pic s9(18) comp-5 is typedef.
$ELSE
77 long pic s9(9) comp-5 is typedef.
$END
77 d-float comp-2 is typedef.
77 float comp-1 is typedef.
01 i pic s9(9) comp-5.
01 strlength pic s9(9) comp-5.
01 ptrStr pointer value null.
01 cobol-int int.
01 cobol-long long.
01 cobol-double d-float.
01 cobol-float float.
*> this is known a c string array of char x'00' terminated
01 cobol-char pic x(25) value all x"00".
01 result pic 9(4) comp-x.
01 USQ1-DBENV PIC X(32) VALUE "BM_DB ".
01 USQ1-DBNAME PIC X(32).
01 USQ1-DBUSER PIC X(32).
01 USQ1-SIGNON PIC X(100).
LINKAGE SECTION.
*>
*> show how to accept a integer and a array of pointers
*> The main key to this is using the set address
*> basically have to convert a cobol pointer to a c pointer
*>
01 argc usage int.
01 argv usage pointer.
*>
*> when using set address need to declare variables inside
*> the linkage section.
*>
01 lkStr pic x any length.
01 lkPtrTB.
02 lkPtr pointer occurs 99.
PROCEDURE DIVISION using by reference argc
by reference argv.
main section.
main-010.
display " In COB acceptingfromc:main"
perform init
perform work
perform fini
.
main-090.
goback.
init section.
init-010.
display " In COB acceptingfromc:init"
display 'ARGUMENTS GIVEN: ' argc
set address of lkPtrTB to argv
perform varying i from 2 by 1 until i > argc
move lkPtr(i) to ptrStr
set address of lkStr to ptrStr
if address of lkStr not = null
call "strlen" using lkStr
returning StrLength
if StrLength > 100
display "COB cobcmd <" StrLength
"> string <" lkStr(1:100) ">"
"... (" StrLength " BYTES)"
else
display "COB cobcmd <" StrLength
"> string <" lkStr(1:StrLength) ">"
end-if
end-if
end-perform
.
init-090.
exit.
work section.
work-010.
display " In COB acceptingfromc:work"
*> pasing the simple types acroos
move 9999 to cobol-double
*> pass one error across check return code in result
move 101 to cobol-long
move 10.5 to cobol-float
move -10 to cobol-int
move "abcdefghijklmnopqrst" & x"00" to cobol-char
call "csub1" using by value cobol-int
by reference cobol-float
by reference cobol-long
by reference cobol-char
by reference cobol-double
returning result
display "Result from csub1 <", result, ">"
.
work-090.
exit.
fini section.
fini-010.
display " In COB acceptingfromc:fini"
move "username1" & x"00" to USQ1-DBUSER
move z"mydbname" to USQ1-DBNAME
string "//" delimited by size
USQ1-DBENV delimited by space
"/" delimited by size
USQ1-DBNAME delimited by x"00"
QUOTE delimited by size
USQ1-DBUSER delimited by x"00"
QUOTE delimited by size
x"00" delimited by size
INTO USQ1-SIGNON
*> These strings must be x'00' terminated
*> just for testing USQ1-DBENV is not x"00" terminated
call "MCC807" using by reference USQ1-DBENV
by reference USQ1-DBNAME
by reference USQ1-DBUSER
by reference USQ1-SIGNON
returning result
display "Result from MCC807 <", result, ">"
.
fini-090.
exit.
end program acceptingfromc.
<<<<<<<<<<<<
>>>>>>>>>>>
/*
* acceptingfromcob.c
*
* Created on: 16 Oct 2012
* Author: tonyt
*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
int csub1(int a_int, float *bptr_float, long *cptr_long, char *dptr_char, double *eptr_double)
{
printf("In C acceptingfromcob:csub1\\n");
int result = 0;
if(a_int == -10)
{
printf("int passed correctly <%d>\\n", a_int);
}
else
{
printf("int failed <%d>\\n", a_int);
result = result 1;
}
if(*bptr_float == 10.5)
{
printf("float passed correctly <%f>\\n", *bptr_float);
}
else
{
printf("float failed <%f>\\n", *bptr_float);
result = result 10;
}
if(*cptr_long == 10)
{
printf("long passed correctly <%d>\\n", *cptr_long);
}
else
{
printf("long failed <%d>\\n", *cptr_long);
result = result 100;
}
if(strcmp(dptr_char, "abcdefghijklmnopqrst") == 0)
{
printf("char * passed correctly <%s>\\n", dptr_char);
}
else
{
printf("char * failed <%s>\\n", dptr_char);
result = result 1000;
}
if(*eptr_double == 9999)
{
printf("double passed correctly <%lf>\\n", *eptr_double);
}
else
{
printf("double failed <%lf>\\n", *eptr_double);
result = result 10000;
}
return(result);
}
int MCC807(char *cptr_env, char *cptr_name, char *cptr_user, char *cptr_signon)
{
printf("In C acceptingfromcob:MCC807\\n");
int result = 0;
printf("env <%s>\\n", strndup(cptr_env, 32));
printf("name <%s>\\n", cptr_name);
printf("user <%s>\\n", cptr_user);
printf("signon <%s>\\n", cptr_signon);
return(result);
}
/**
*** test the customer using cobcall to access this entry point
*** InitCDBaseRate
**/
#define PROGRAMID_SIZE 8
#define PARAGRAPHID_SIZE 20
typedef struct
error_struct
{
char sProgramID[PROGRAMID_SIZE] ; /* Pgm or Module where error occured*/
char sParagraphID[PARAGRAPHID_SIZE] ; /* Section of code*/
}
ERROR_STRUCT;
#define BANK_ID_SIZE 4
#define CURRENT_USER_SIZE 4
typedef struct control_struct
{
char sBankId[BANK_ID_SIZE];
char sCurrentUser[CURRENT_USER_SIZE];
char *pInstancePtr;
}
CONTROL_STRUCT;
/**
*** they have dll_export = _export ? problem with __export
*** they have DLL_CALLBACK _far and _pascal but the endif in declare is not correct ?
**/
#define DLL_EXPORT
#define DLL_CALLBACK
#if 0
typedef enum status
{
EXCEPTION = (-1),
SUCCESS = 0 ,
FAILURE = 1 ,
WARNING = 2
}
STATUS;
#endif
#ifndef STATUS
#define STATUS int
#endif
#ifndef EXCEPTION
#define EXCEPTION (-1)
#endif
#ifndef SUCCESS
#define SUCCESS 0
#endif
#ifndef FAILURE
#define FAILURE 1
#endif
#ifndef WARNING
#define WARNING 2
#endif
STATUS DLL_EXPORT DLL_CALLBACK InitCDBaseRate(ERROR_STRUCT *pErrorDetails, CONTROL_STRUCT *pControl)
{
void *pInstance;
printf("\\nInside InitCDBaseRate...\\n");
/**
*** lets just display what we have passed across
**/
printf("perrordetails <%s>\\n", strndup(pErrorDetails, sizeof(ERROR_STRUCT)));
printf("pControl <%s>\\n", strndup(pControl, sizeof(CONTROL_STRUCT)));
printf("pControl : %p...\\n",pControl);
printf("pControl->pInstancePtr : %p...\\n",pControl->pInstancePtr);
printf("returning from InitCDBaseRate");
return EXCEPTION;
}
>>>>>>>>>>>>>
/*
* passingtocob.c
*
* Created on: 16 Oct 2012
* Author: tonyt
*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
#define MAXPARAMS 2
main(int argc, char *argv[])
{
int i;
printf("In C passingtocob:main\\n");
/**
*** Now we need to initialise the Cobol system before we
*** start making any calls to Cobol.
**/
cobinit();
/**
*** Just print the data passed to program from command line
**/
for (i = 1; i < argc; i )
printf("C main length <%d> string <%s>\\n", strlen(argv), strndup(argv 0, 100));
printf("\\n");
char *pcFunction;
pcFunction="acceptingfromc";
/**
*** acceptingfromc has two linkage parameters a interger"argc" a array of pointers to string"argv"
*** just showing this to show what cobcall is actually doing and expecting.
**/
void *acceptingfromcinputarray[2];
acceptingfromcinputarray[0]=&argc;
acceptingfromcinputarray[1]=&argv;
cobcall(pcFunction, 2, acceptingfromcinputarray);
char *inputarray[3] = {"dummyprogname", "string1", "string2"};
void *ptrinputarray = &inputarray;
for (i = 0; i < 3; i )
printf("inputarray string len <%d> string <%s>\\n", strlen(inputarray), strndup(inputarray 0, 100));
printf("\\n");
i = 3;
acceptingfromcinputarray[0]=&i;
acceptingfromcinputarray[1]=&ptrinputarray;
cobcall(pcFunction, 2, acceptingfromcinputarray);
/**
*** Just call the program not using cobcall
**/
acceptingfromc(&argc, &argv);
/**
*** To the customers problem using cobcall to call a c routine
**/
long lRv = 0;
char *ppParameter[MAXPARAMS];
int iParameterCount;
pcFunction="InitCDBaseRate";
iParameterCount=2;
printf("\\nInside testcobcall...well sort of actually in <%s>\\n", argv[0]);
ppParameter[0]="8765432112345678901234567890";
ppParameter[1]="43211234xxxxxxxx";
printf("pControl : %p...\\n",ppParameter[1]);
lRv = cobcall(pcFunction, iParameterCount, ppParameter);
printf("lRv <%d>\\n", lRv);
/**
*** Now we just need to de-initialise the Cobol system.
**/
cobtidy();
char ans;
printf("press enter to exit>\\n");
ans = getchar();
printf("Bye\\n");
return 0;
}
>>>>>>>>>>>>>>>