Highlighted
Absent Member.
Absent Member.
2163 views

[archive] Calling C code from COBOL problems

[Migrated content. Thread originally posted on 16 August 2003]

Hi,

I've got all sorts of problems related to this.

It's to do with emulating HP MPE stuff so the syntax of some of this code is HP specific so you have to use the "-Cp" option with ACU 6.

The problem is with code like this -

WORKING-STORAGE SECTION.
01 pvalue PIC S9(4) COMP VALUE 40.

PROCEDURE DIVISION.
LEVEL-1 SECTION.
blah
CALL "hp3_cobol.dll"
* this passes pvalue by reference
CALL "PARMTEST" USING pvalue pvalue.
* this passes 40 by value
CALL "PARMTEST" USING \5\ \40\.
* this passes pvalue by value but gives 10240 (wrong byte order)
CALL "PARMTEST" USING \5\ pvalue


In the DLL I have a bit of C code which get's 3 different values for the 2nd parameter as described in the COBOL comments above. I can cope with getting a by value or a by reference due to a dirty hack. If the value is >= 0xffff then I assume it's by reference and convert.

But in this example, if you pass a constant first, it then decides to pass the 2nd one by value but gets the byte ordering wrong.

What can I do?

I can't change the COBOL code really as the whole point of the -Cp flag is that you can compile your COBOL code as is (we're doing a migration - not a re-write). Although, as a last resort, I could probably change the working storage if that helped but I wouldn't know what to change it to.

Cheers

Peter
0 Likes
8 Replies
Highlighted
Absent Member.
Absent Member.

RE: [archive] Calling C code from COBOL problems

Although I can't use sub.c for other reasons, I thought I'd see if it helped here so I added

if (strcmp(argv[0], "PARMTEST2") == 0) { PARMTEST (argv[1], argv[2]); return 0;}

to sub.c and re-linked the runtime.

Now everything is passed by reference (as documented) but now /40/ gets passed with the wrong byte order and "pvalue" is OK in both cases!
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Calling C code from COBOL problems

As you are referring to the use of a DLL here, I assume you are using the Windows runtime? Hence, I also assume the DLL in question is a Windows DLL. In which case, it is most likely it uses the WinAPI calling convention. Thus, your problem is that it seems like you are not setting the DLL-CONVENTION configuration switch properly. Try inserting this as the first statement of your code:

SET ENVIRONMENT "DLL-CONVENTION" TO "1".

To be sure I provide you with the right information, would you mind share with us, the documentation (declaration) of the DLL function you are calling?
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Calling C code from COBOL problems

Thanks for the reply. I've worked around the problem after finding out how to use sub85.c which tells me what byte order each parameter is in so I can convert as required.

Here is my DLL declaration DLLEXP is just a #define for _declspec(dllexport). I'll look at that environment option you mentioned. I'm not sure how it could be related though as the sub85.c interface is returning different argument types (args.a_type values).

#include

void dispval (char *param)
{
int value, value2;
char valueStr[256];

/* This is an awful hack! */
if ((int)param
{
/* probably BY VALUE */
value = (int)param;
/* Seem to get the value passed incorrectly sometimes */
value2 = (value & 0xff)<
value2 += (value &0xff00) >> 8;
sprintf(valueStr, "by value %d or if byte order correction required %d",
value, value2);
}
else
{
/* probably an address so convert from COBOL number to C */
/* Forget -ve values for this simple test */
value = (int) (param[0]&0xff)* 256 + (param[1]&0xff);
value2 = (int) (param[1]&0xff)* 256 + (param[0]&0xff);
sprintf(valueStr, "by ref %d", value);
}


/* Have to use MessageBox as I don't know how to call DISPLAY code. */
MessageBox(NULL, valueStr, "PARMTEST", MB_OK);
}

DLLEXP int PARMTEST(char *param, char *param1)
{
dispval (param1);
return 2;
}
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Calling C code from COBOL problems

I am not sure why you want to use sub85 to call a DLL. However, if you want to do that, your forward declaration of the DLL function will resolve the calling convention, this because you call the function in C rather than COBOL.
Doing this, is however much more complicated and error prone than using a dynamic link from COBOL. From the information you have provided this far, I cannot see that you call any DLL function yet.

If you can provide me with the spec for the DLL function and the name of the DLL I will give you a sample.

Also, for your information, I have recently had two training session in Europe (Tilburg Holland, M?nchen Germany) named "Advanced Windows API, ActiveX and COM programming techniques". This full day course goes in depth about interfacing DLLs and COM (MS Office) from within ACUCOBOL-GT. Describing techniques and providing lots of sample code and exercises.

If you feel that you could need some more info in this area, perhaps this could be a course to attend.

There is another one coming up in Tilburg September 19th, but this one is full.

There is about to be scheduled one in London later this fall if there is demand. You may contact your account manager or monitor http://www.acucorp.com/events if interested.
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Calling C code from COBOL problems

Now that I have used sub85.c I can see that it is nothing to do with calling DLL's. The ACU run-time is not being consistent in the byte ordering for the parameters sent in my example COBOL program.

I can send a sub85.c example which demonstrates the arguments passed are sometimes in native byte ordering and sometimes in COBOL COMP byte ordering. But at least the sub85 interface tells me what the byte ordering is so I can work around it.

The sub85 interface tells me that sometimes the parameters is a COMP-1 variable and sometimes a COMP-5 variable. It's odd but I can cope with it!

Thanks for your help.

Peter
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Calling C code from COBOL problems

The ACUCOBOL-GT is indeed being consistent in its parameter passing. If you are happy about using the sub85 interface that is great, but I believe that once you learn the trick, accessing DLLs directly is easier and more dynamic.
However, I am happy that you now has it all set.
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Calling C code from COBOL problems

I've been calling DLL's dynamically for a few years without any problems.

The problem I'm having now is related to the new MPE/HP3000 syntax which allows you to pass by value as shown in my example program. This (at least to me) alters the byte order of COMP-1 values.

I had to use the sub85.c interface for another reason - Variable parameter lists.

On MPE you're allowed to do things like this

call "myintrinsic" using a b c
call "myintrinsic" using a b

Using the dynamic method, there's no way to know how many parameters you've been given. I could even do a bit of parameter type checking in there when I've got time.

Some of the intrinsics take up to 20 parameters - usually only the first few are specified. These are OS intrinsics we are emulating so it's not as if we can change that.

The sub85.c also has the nice bonus that we don't have to add call "ourdll.dll" to all the code. Although getting our customers to re-link the run-time can be a pain! We usaully only do that on UNIX.


Cheers

Peter
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Calling C code from COBOL problems

What would really be nice (at least with the Windows runtime) is to have the ability to put sub85.c in a DLL instead of relinking the runtime, like you can now do with sub.c.

We use sub85.c because we can use a variable number of parameters in the CALL and we can get data type/size information for each of the parameters.
0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.