|National Language Support (NLS) Demonstration||Interfacing and Mixed-language Programming|
This system can compile COBOL programs to standard Intel native object code (.obj) files, of the same type as those produced by many other language compilers. This makes it possible to create applications using subprograms written both in COBOL and in other languages. Working in a mixed-language environment requires that the run-time support and program interfaces between programs from those different language compilers are consistent.
This chapter explains the call mechanism provided by this COBOL system to help you interface between COBOL and other languages. It describes the problems encountered in interfacing between COBOL and other languages and describes the solutions provided by this COBOL system. You do not need to read this chapter for COBOL-to-COBOL calls.
This chapter describes the COBOL interfacing environment used by DOS, Windows and OS/2. For UNIX see your UNIX documentation.
32-bit on OS/2 V2:
This chapter also describes the Micro Focus Thunking Kit , provided with the 32-bit COBOL system for OS/2 V2. The Thunking Kit enables interfacing between 16-bit and 32-bit modules on OS/2 .
When you have read this chapter, see the chapter Interfacing and Mixed-language Programming for specific details on interfacing between COBOL and the following:
This section considers some of the basic issues involved in mixed-language working so you can get a better understanding of how and when to use the special COBOL syntax for overcoming these problems. It also describes the choice of run-time libraries provided with this COBOL system to be used for creating a mixed-language application as well as the additional syntax available for dealing with the different calling conventions.
Issues that affect the ability of two programs to interface with each other include memory management and the definition of the call interface.
In a mixed-language application it is essential that each different run-time system (RTS) allocates memory in a fashion which still allows the other language run-time systems to satisfy any memory requests they might have.
On DOS , this is done by the main program ensuring that any unused memory is released straight back to the operating system memory pool at the initialization stage. (On DOS, the operating system always allocates the largest available memory block to any programs that it loads.) All language run-time systems should then ensure that they allocate memory from that pool by using standard DOS functions to allocate memory. It is important that all memory requests are moderate. If they are too large there will not be enough memory to satisfy any other memory requests, and if they are too small there is tendency for memory to become fragmented.
Windows and OS/2:
If you are using OS/2 or Windows, applications are already allocating memory through the operating system, so memory management is a far less significant issue.
In order for a call to work it is important that both calling program and called subprogram obey the same rules. The most important of these rules govern:
If the calling program and the called subprogram do not obey the same protocol then the application is liable to crash when the call is made.
Parameters are always passed by pushing the parameters onto the stack before calling the subprogram. The parameters can be pushed onto the stack by either processing the list of call parameters from right-to-left (reverse order) or from left-to-right (order specified). The first of these methods is the convention used by COBOL and by Microsoft C. The second method is used by languages such as Pascal.
Hence, on entry to a subprogram called with the statement:
call "sub-prog" using parameter-1 parameter-2 . . . . . . parameter-n-1 parameter-n
the stack would look like Figure 9-1 if the right-to-left convention was used and like Figure 9-2 if the left-to-right convention was used. In either case, parameters are pushed onto the stack from high memory to low memory. SP is the Stack Pointer register which points to the next vacant slot in the stack.
Figure 9-1: Stack with Right-to-left Convention
Figure 9-2: Stack with Left-to-right Convention
There are two choices as to when the parameters are removed from the stack . They can be removed by the called subprogram before it terminates and returns to the calling program, or by the calling program immediately after it receives control back. In COBOL or Microsoft C, the calling program removes the parameters, while in Pascal the called program removes them.
COBOL supports two methods of passing parameters to a subprogram in a mixed-language environment.
|by reference||Passes a far address (offset:segment on DOS, offset:selector on the 16-bit COBOL system for OS/2 and Windows, or offset on the 32-bit COBOL system). Any changes made to the parameter by the subprogram is reflected in the calling program.|
Passes only the value of the parameter to the subprogram. Any
changes made to the parameter in the subprogram are not reflected in the
If your program uses the shared run-time system on DOS you can only pass parameters by value if XM is also used.
Most languages are capable of passing a return code back to the calling program. The registers used on the 16-bit systems to pass the return code from COBOL and Microsoft C are:
|Return Code Size
COBOL and Microsoft C always assume that these conventions are used by any called program written using any other language.
Most languages assume that the called program preserves certain machine registers. The following registers are preserved by programs written in COBOL and Microsoft C on 16-bit systems:
BP, DS, SI, DI
COBOL and Microsoft C always assume that these same registers are preserved by any called program written using any other language.
The floating-point feature in this COBOL system is fully compatible with the various languages supplied by Microsoft, including Microsoft C V6.0. You should, however, be aware that:
This COBOL system provides various solutions to deal with the mixed-language issues. These solutions come in the choice of run-time libraries to be used for creating the mixed-language application and additional syntax for dealing with the different calling conventions.
The 16-bit COBOL system comes with two alternative run-time libraries which can be used to create an application. Apart from one library being a shared run-time library and the other being a static run-time library, there is one other important difference between the two libraries on DOS: the DOS shared run-time system does not obey the mixed-language memory management protocol. It needs to manage all available memory itself in order to prevent memory fragmentation when running standard COBOL applications.
If you want to perform mixed-language programming with the shared run-time system on DOS, it is possible. You must tell the COBOL RTS, at start up, how much memory should be freed back to the operating system for use by the non-COBOL programs.
This is done by using the COBPOOL environment variable:
integer is the number of kilobytes to be
released back to the operating system.
If a large value is specified for
memory available to the COBOL system and the application is reduced. This
can leave insufficient memory to run the COBOL system or the application.
As the RTS requires at least 256K of free memory, you must ensure that
this minimum amount remains available to the RTS.
Your Language Reference describes COBOL syntax intended to deal with the various program-to-program interface issues described earlier. The following sections explain how to use some of these features.
COBOL programs can call and be called by programs written in other languages. However, some languages handle calls differently from COBOL. For example, some language pass parameters in the opposite order from that expected by COBOL programs. To enable COBOL and non-COBOL programs to call each other, you can adjust the calling mechanisms that the COBOL program uses or that it expects to be used.
To specify the calling mechanisms you require, you first construct the call convention number that produces the required mechanisms.
The call convention number is a 16-bit number defined as follows:
On the 16-bit COBOL system, reserved (always 0)
On 32-bit COBOL systems the following additional conventions are available:
|7-15||Reserved (always 0)|
When you have constructed the call convention number, convert it to a decimal number, and then assign this decimal number to a name, by defining it in the Special Names paragraph. You then use the call convention name in the CALL statement.
For example, you could define the following:
special-names. call-convention 0 is microsoft-c call-convention 3 is Pascal.
The mnemonic-name defined could then be used to specify the convention to be used on a CALL statement by:
call microsoft-c "routine-name" using param-1,...,param-n
or to specify the convention that this program should expect to be called with by using the syntax:
procedure division Pascal using param-1,...,param-n
If no call convention is specified, the standard COBOL convention is assumed (CALL-CONVENTION 0).
A parameter which is to be passed or received by value should be preceded by the BY VALUE phrase as documented in your Language Reference. You should ensure that any parameter passed by value is always an even number of bytes. The value of any parameter passed by value is always pushed onto the stack so that the lowest addressed byte is the last to be pushed. A parameter passed by value can be up to four bytes long.
If no SIZE clause is specified, the number of bytes passed is determined by the LITVAL-SIZE directive, which defaults to four.
call "routine-name" using by value 2 size 2.
passes a two-byte value of 2.
The format for most of the COBOL data types is described in the Language Reference. The following data types are the types which are relevant to mixed-language programming:
|COMP-X||Data is stored with the most significant byte first; that is, the most significant byte is at the lowest address. Although this is standard COBOL format, it is the reverse of the Intel standard of storing the most significant byte last.|
|COMP-5||Defined as Intel reverse byte storage format, in which data is stored with the least significant byte first; that is, the least significant byte is at the lowest address. Using this data-type enables you to pass parameters directly from COBOL to non-COBOL programs without parameter conversion.|
POINTER and PROCEDURE-POINTER
Always stored as 32-bit quantities in Intel double-word reversed byte format.
On the 16-bit COBOL system the first word is the offset, and the second word is the segment on DOS, or selector on Windows and OS/2.
On 32-bit COBOL systems the entire format is a double-word reversed byte offset.
Pointer variables are extremely useful for holding the address of a dynamically allocated memory area. COBOL programs can then access this memory using the SET ADDRESS statement.
In languages such as C and assembler it is normal for numeric items to be aligned on word or double-word boundaries. Provided you use the ALIGN directive with a parameter which is a multiple of four, all 01-level items are aligned on a double word boundary.
The Compiler users ALIGN"8" by default.
If you are passing numeric parameters that are not level-01 data items in the COBOL program, or are in a parameter block passed as a single item, it is important that you make sure they are correctly aligned.
There are two different methods for handling return codes passed back from a called subprogram to the calling program. The first method is to make use of the COBOL special register, RETURN-CODE. The register is given a value in the COBOL subprogram before that subprogram passes control back to the COBOL calling program with an EXIT PROGRAM or GOBACK statement. The RETURN-CODE register of the calling program is then automatically updated with the subprogram's return code and this register can be examined accordingly. The RETURN-CODE register is predefined as PIC S9(4) COMP (unless the program has been compiled with the RTNCODE-SIZE "4" directive when it is PIC S9(8) COMP) which, while being suitable for COBOL-to-COBOL interprogram communication, is not really flexible enough to deal with calls to non-COBOL subprograms.
The preferred, and more flexible, way of handling return codes to and from COBOL programs in mixed-language applications is to make use of the RETURNING phrase on the CALL, EXIT PROGRAM, GOBACK, STOP RUN statements. This syntax enables you to define the format of the return code yourself and so cope with whatever size of return code you require
If either of the above methods is used to return a value back to the operating system, to be examined by the operating system IF ERRORLEVEL syntax, it should be noted that the operating system limits this value to one byte on 16-bit DOS and Windows, and two bytes on 32 bit systems.
This section is only applicable to OS/2 V2. It describes how to interface between 16-bit and 32-bit modules. It assumes a knowledge of the differences between 16-bit and 32-bit architecture and a good understanding of language calling conventions.
OS/2 V2 enables execution of both 16-bit and 32-bit applications, including the mixing of 16-bit and 32-bit modules in the same application. Interfacing between the 16-bit and 32-bit modules is referred to as thunking. This COBOL system provides a means of implementing thunking by using a call convention. This provides support for most call interfaces. Call convention 32 provides the thunking interface (see the section Call Conventions for information on call conventions).
By using the call convention you can create a seamless interface to your existing 16-bit support modules, thus enabling you to use any existing support modules without recoding or recompiling the 16-bit .dll files.
Figure 9-3 illustrates 32-bit to 16-bit thunking.
Figure 9-3: 32-bit to 16-bit thunking
The following example demonstrates how to call an existing 16-bit C support module (CSWAP) from a 32-bit application using a thunk interface. Given the existing software, you could create a thunk interface using the call convention as in the following example
$set rtncode-size"4" environment division. special-names. call-convention 32 is thunked. data division. working-storage section. 01 pptr16 pic xxxx comp-5. 01 ptrnum pic xx comp-5 value1. linkage section. 01 ws-item1 pic xx comp-5. 01 ws-item2 pic xx comp-5. procedure division using by value ws-item1 by reference ws-item2. call thunked "cswap" using by value ws-item2 by reference ws-item2. exit program. stop run.
Items of USAGE POINTER passed to the called program need to be converted, using the routines described in the next section. Using call convention 32 automatically thunks to a 16-bit function and converts all BY REFERENCE parameters
Two API routines are supplied that allow conversion of USAGE POINTER data items from a 32-bit address to a 16-bit address and vice-versa. These routines are described below. The case of these API items must be preserved, so a COBOL program that uses them must be compiled using the CASE compiler directive.
Converts from a 32-bit address to a 16-bit address.
'_mFseltoflat' using by value mypointer-32 returning mypointer-16
|mypointer-32||32:0 flat address|
|mypointer-32||16:16 segmented address|
This routine is called from 32-bit applications. The 32:0 flat address is converted to a 16:16 segmented address.
Converts from a 16-bit address to a 32-bit address.
call '_mFflattosel' using by value mypointer-16 returning mypointer-32
|mypointer-16||16:16 segmented address|
|mypointer-32||0:32 flat address|
This routine is called from 16-bit applications. The 16:16 segmented address is converted to a 0:32 flat address.
For details of Compiler directives see the appendix Directives for Compiler in your Object COBOL User Guide. For details of COBOL syntax see your Language Reference.
Copyright © 1999 MERANT International Limited. All rights reserved.
This document and the proprietary marks and names used herein are protected by international law.
|National Language Support (NLS) Demonstration||Interfacing and Mixed-language Programming|