How to Pass Parameters Between COBOL and C

Michael Hendrick
Systems Support Engineer, Languages

February 1992

Abstract

This article explains how Microsoft® COBOL programs can pass parameters to and receive parameters from Microsoft C programs. It assumes you have a basic understanding of the COBOL and C languages.

Microsoft COBOL supports calls to routines written in Microsoft C, FORTRAN, Pascal, and Assembler. This article describes the necessary syntax for calling Microsoft C routines and contains a series of examples demonstrating the interlanguage capabilities between COBOL and C. The sample programs apply to the following Microsoft products:

Mixed-Language Programming with COBOL and C

The C Interface to COBOL

The C interface to COBOL utilizes the standard C extern statement. The following are the recommended steps for using this statement to execute a mixed-language CALL from C:

  1. In the C code, include an extern statement for each COBOL routine CALLed. The extern statement should be at the beginning of the C program, before any CALLs to the COBOL routine.

    Note: When compiling, if the /Gc compiler directive is used (the /Gc option causes all functions in the module to use the FORTRAN/Pascal naming and CALLing conventions), then the cdecl keyword should be used when the COBOL function is declared (because COBOL uses the C CALLing convention, not the Pascal CALLing convention).

  2. To pass an argument by reference, pass a pointer to the object (all parameters must be passed by reference to COBOL).

    C automatically translates array names into addresses. Therefore, arrays are automatically passed by reference and don't need the * (asterisk) operator.

  3. Once a routine has been properly declared with an extern statement, CALL it just as you would CALL a C function.

  4. If passing structures between COBOL and C, compile the C routine with the /Zp1 compiler option to pack structure members.

  5. Always compile the C module in large model.

C Arguments

The default for C is to pass all arrays by reference (near or far, depending on the memory model) and all other data types by value. C uses far data pointers for compact, large, and huge models, and near data pointers for small and medium models.

Passing C Arguments by Value

The C default is to pass everything except arrays by value.

Arrays can be passed by value only if they are declared as the only member of a structure. The following example passes all 100 bytes of x directly to the C function test():

struct x_struct {int x[100]) xs;
.
.
.
test(xs)

Passing C Arguments by Reference (Near or Far)

In C, passing a pointer to an object is the equivalent of passing the object itself by reference. Within the CALLed function, each reference to the parameter itself is prefixed by an * (asterisk).

Note:     To pass a pointer to an object, prefix the parameter in the CALL statement with &. To receive a pointer to an object, prefix the parameter's declaration with *. In the latter case, this may mean adding a second * to a parameter that already has an *. For example, to receive a pointer by value, declare it as follows:

int   *ptr;

But to receive the same pointer by reference, declare it as the following:

int   **ptr;

The default for arrays is to pass by reference.

Effect of C Memory Models on Size of Reference

Near reference is the default for passing pointers in small and medium model C. Far reference is the default for the compact, large, and huge models.

Note   All C programs that are linked with COBOL must be compiled with the large memory model.

Restrictions on CALLs from COBOL

The COBOL to C interface does not support near heap in the C run time. This means you should not use the function calls that access near heap in your C programs. This includes the following functions:

To work around this, compile and link with C as the initial program. After the main C program begins, the COBOL routine can be CALLed. The COBOL code can then CALL back and forth with C. Since the C support modules are not used, there are no special restrictions on the near heap functions.

Special Note on C Strings

C stores strings as simple arrays of bytes (like COBOL) but also uses a null character [ASCII NULL (0)] as the delimiter to show the end of the string. For example, consider the string declared as follows:

char str[] = "String of text"

The string is stored in 15 bytes of memory as follows:

|S|t|r|i|n|g| |o|f| |t|e|x|t|\0|

When passing a string from COBOL to C, the string will normally not have a NULL appended to the end. Because of this, none of the C routines that deal directly with a string (printf, sprintf, scanf, and so on) can be used with these strings unless a NULL is appended to the end.

A NULL can be put at the end of a COBOL string by using the following declaration:

01 CSTRING.
   05 THE_STRING PIC X(10).
   05 FILLER PIC X VALUE x"0".

Compiling and LINKing

Several compile and link options need to be used when interfacing C and COBOL. The standard C compile line is as follows:

CL /c /Aulf CProgName ;
Option Description
/c Compiles without linking (produces only an .OBJ file).
/Aulf Sets up a customized large memory model.
u SS not equal to DS. DS is reloaded on function entry.
l Selects large memory model Far (32-bit) code pointers.
f Selects large memory model Far (32-bit) data pointers.

The standard LINK line for COBOL CALLing C is as follows:

For MS-DOS®

LINK CobProg CProg MFC6INTF C6DOSIF C6DOSLB,,,LCOBOL COBAPI 
     LLIBCE/NOE/NOD;

For OS/2®

LINK CobProg CProg MFC6INTF C6OS2IF C6OS2LB,,,LCOBOL OS2 
     LLIBCEP/NOE/NOD;

The standard LINK line for C CALLing COBOL is as follows:

For DOS

LINK CProg CobProg,,,LLIBCE LCOBOL COBAPI/NOE/NOD;

For OS/2

LINK CProg CobProg,,,LLIBCEP LCOBOL OS2/NOE/NOD;

Note that the order in which the libraries are specified in the LINK line is important.

Microsoft® COBOL versions 4.0 and 4.5 introduced the shared run-time system. Although it is generally more useful to link your applications using the static run-time system (LCOBOL.LIB), you may also choose to link the applications with the shared run-time library (COBLIB.LIB) to take advantage of its more efficient methods of utilizing memory. In order to do this and link your applications to Microsoft C, you must SET the COBPOOL environment variable as referenced in the Microsoft COBOL Operating Guide.

Common Pitfalls

This list supplies a simple checklist to go over when you encounter problems doing mixed-language programming:

Batch FIles

The following batch files can be helpful when using the sample programs below. The CBC6.BAT file can be used to set your environment table correctly, but think of it as a convenience rather than a necessity when using. This means that you should already have these parameters preset in your environment when using both languages in tandem.

CBC6.BAT

REM THIS BATCH FILE SHOULD CONFIGURE THE ENVIRONMENT TABLE TO ENABLE 
REM YOU TO COMPILE BOTH THE C AND COBOL APPLICATIONS UNDER MS-DOS 
REM CORRECTLY.
REM
REM PLEASE LOOK CLOSELY AT THE ENVIRONMENT SETTINGS AND CHANGE THOSE
REM NECESSARY IN YOUR OWN AUTOEXEC.BAT FILE.
REM
REM NOTE: IF, AFTER INVOKING THIS BATCH FILE, YOU SEE THE MESSAGE 
REM "OUT OF ENVIRONMENT", YOU WILL HAVE TO INCREASE THE AMOUNT OF 
REM ENVIRONMENT TABLE SPACE. PLEASE SEE YOUR MS-DOS MANUAL UNDER THE 
REM HEADING COMMAND.COM FOR INSTRUCTIONS ON HOW TO DO THIS.
REM
SET LIB=C:\COBOL\LIB;C:\C600\LIB
SET INCLUDE=C:\C600\INCLUDE;C:\COBOL\SOURCE
SET HELPFILES=C:\C600\HELP\*.HLP
SET INIT=C:\C600\INIT;C:\COBOL\INIT
PATH=C:\COBOL\BINB;C:\COBOL\BINR;C:\C600\BINB;C:\C600\BIN;C:\DOS

RUN.BAT

REM THIS BATCH FILE CAN BE USED TO COMPILE AND LINK BOTH THE C AND 
REM COBOL APPLICATIONS FOR MS-DOS.
REM
REM THOSE PROGRAMS THAT REQUIRE A DIFFERENT METHOD OF COMPILING AND 
REM LINKING WITHIN THE SCOPE OF THIS APPLICATION NOTE WILL BE NOTED.
REM
REM TO INVOKE THIS BATCH FILE, YOU MUST ENTER THE BATCH FILE NAME, 
REM FOLLOWED BY THE C PROGRAM NAME (WITH NO EXTENSION), FOLLOWED BY 
REM THE COBOL PROGRAM NAME. FOR EXAMPLE:
REM
REM             RUN <C PROGRAM NAME> <COBOL PROGRAM NAME>
REM
cl /c /Aulf %1.c
COBOL %2;
LINK %2  %1 MFC6INTF C6DOSIF C6DOSLB,,,LCOBOL COBAPI LLIBCER /NOD/NOE;

RUN_C.BAT

REM THIS BATCH FILE CAN BE USED TO COMPILE AND LINK UNDER MS-DOS 
REM ONLY WHEN THE SAMPLE C CODE IS CALLING A COBOL PROCEDURE.
REM
REM THOSE PROGRAMS THAT REQUIRE A DIFFERENT METHOD OF COMPILING AND 
REM LINKING WITHIN THE SCOPE OF THIS APPLICATION NOTE WILL BE NOTED.
REM
REM TO INVOKE THIS BATCH FILE, YOU MUST ENTER THE BATCH FILE NAME, 
REM FOLLOWED BY THE C PROGRAM NAME (WITH NO EXTENSION), FOLLOWED BY 
REM THE COBOL PROGRAM NAME. FOR EXAMPLE:
REM
REM             RUN <C PROGRAM NAME> <COBOL PROGRAM NAME>
REM
cl /c /Aulf %1.c
COBOL %2;
LINK %1  %2,,,LLIBCER LCOBOL COBAPI/NOD/NOE;

WINRUN.BAT

REM THIS BATCH FILE IS USED TO COMPILE AND LINK THE QUICKWIN 
REM APPLICATION PROGRAM DEMONSTRATED IN THIS DOCUMENT. THIS IS A 
REM SPECIALIZED BATCH FILE. IT HAS BEEN CREATED SPECIFICALLY FOR THE 
REM SAMPLE PROGRAM PRESENTED.
REM TO CREATE A GENERIC BATCH FILE, CHANGE ALL OCCURRENCES CDLL AND 
REM TEST TO %1 AND %2 RESPECTIVELY.
REM
cl /ML /Gs /c /Zi CDLL.C
LINK CDLL+LIBENTRY,CDLL.DLL,CDLL.MAP/MAP,LDLLCEW+LIBW/NOE/NOD,CDLL 
     /CO;
IMPLIB CDLL.LIB CDLL.DLL
COPY CDLL.DLL C:\
COBOL TEST TARGET(286);
LINK CBLWINC+TEST+ADIS+ADISINIT+ADISKEY,TEST.EXE,,LIBW+LLIBCEW+LCOBOL+
     COBAPIDW+CDLL.LIB,TEST.DEF/NOE/NOD;

Sample Code

The following sample code demonstrates how to pass common numeric types to a C routine by reference and by value.

COBNUMS.CBL

      * Passing Common Numeric Types to C by Reference and by Value
       working-storage section.
       01 field1 pic 9(4) comp-5 value 123.
       01 field2 pic 9(8) comp-5 value 123456.
       01 field3 pic 9(4) comp-5 value 456.
       01 field4 pic 9(8) comp-5 value 456789.
       procedure division.
      * Fields 1 and 2 (below) are passed BY REFERENCE. The keywords
      * are omitted here since BY REFERENCE is the default method.
       call "_CFUNC" using field1, field2,
                          by value field3,
                          by value field4.
       display "Returned pic 9(4): " field1.
       display "Returned pic 9(8): " field2.
       stop run.

CFUNC.C

#include <stdio.h>
void CFunc(int *RefInt, long *RefLong, int ValInt, long ValLong)
{
   printf("By Reference: %i %li\r\n", *RefInt, *RefLong);
   printf("By Value    : %i %li\r\n", ValInt, ValLong);

   *RefInt = 321;
   *RefLong = 987654;
}

OUTPUT

Returned PIC 9(4): 00321
Returned PIC 9(8): 000987654
By Reference: 123 123456
By Value    : 456 456789

The following sample code demonstrates how to pass an alphanumeric string from C to COBOL.

_COBPROG.CBL

       program-id. "_cobprog".
       data division.
       linkage section.
       01 field1 pic x(6).

       procedure division using field1.
       display "String from C: " field1.
       stop run.

C.C

#include <stdio.h>
extern cdecl cobprog(char *Cptr);
char Cptr[] = "ABCDEF";
void main() {
   cobprog(Cptr);
}

Output

String from C: ABCDEF

The following sample code demonstrates how to pass a record from COBOL to a C data struct.

STRUCT.CBL

      $set vsc2  rtncode-size(4)
      * Passing a Record from COBOL to a C struct
       data division.
       working-storage section.
       01 rec-1.
          02 var1  pic X(8)  value "HELLO".
          02 var2  pic X(12) value "W O R LD".
          02 varc2 pic 9(04) comp-5 value 2.
          02 varc3 pic 9(04) comp-5 value 3.
          02 varc4 pic 9(04) comp-5 value 4.
          02 varc5 pic 9(04) comp-5 value 5.
          02 varc1 pic 9(04) comp-5 value 1.

       procedure division.
       call "C_FUNCTION1" using by reference rec-1.
       display "CBL varC--> " varC1.
       display "CBL varC--> " varC2.
       display "CBL varC--> " varC3.
       display "CBL varC--> " varC4.
       display "CBL varC--> " varC5.
       display "CBL var1--> " var1.
       display "CBL var2--> " var2.
       stop run.

STRUCTC.C

#include <stdio.h>
struct struct1 {
   unsigned char var1[8];
   unsigned char var2[12];
   unsigned int  var3[5];
};
 
function1(struct struct1 far *p1)
{
   int a;
   for (a=0; a<5; a++)
      printf("%i\n",p1->var3[a]);
 
   for (a=0; a<8; a++)
      printf("%c", p1->var1[a]);
      printf("\n");
 
   for (a=0; a<12; a++)
      printf("%c", p1->var2[a]);
   printf("\n");
}

OUTPUT

2
3
4
5
1
HELLO
W O R LD
CBL VARC--> 00001
CBL VARC--> 00002
CBL VARC--> 00003
CBL VARC--> 00004
CBL VARC--> 00005
CBL VAR1--> HELLO
CBL VAR2--> W O R LD

The following sample code demonstrates how to pass a record from struct from C to COBOL.

_COBPROC.CBL

       identification division.
       environment division.
       data division.
       working-storage section.
       01 Integer              pic 9(4).
       01 Long                 pic 9(8).
       linkage section.
       01 CobRec.
          03 COBInt            pic s9(4) comp-5 value zero.
          03 COBLong           pic s9(8) comp-5 value zero.
          03 COBString         pic x(21) value spaces.
       procedure division using CobRec.
       move COBInt to Integer.
       move COBLong to Long.
       display "Integer from C: " Integer.
       display "Long integer from C: " Long.
       display "String from C: " COBString.
       exit program.

STRUCT2C.C

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
     struct CobRec             // defines data type CobRec
     {
        unsigned int varInt;   // integer variable 
        unsigned long varLong; // long int
        char szString[21];     // string variable
     };

/* COBOL routines are cdecl; this means the name must be prefixed
 * with '_'. Alternatively, you can manually reverse the
 * parameters.
 */
extern far cdecl COBPROC(struct CobRec *cPtr);

main() 
{
   struct CobRec *cPtr;        // declare pointer to struct

                               // get memory to hold struct
   cPtr = (struct CobRec *) _fmalloc(sizeof(struct CobRec));

/* NOTE: COBOL will be the main program unless BP is nonzero.
 * BP is zero until some local variables are allocated and used.
 *
 * In this example, we do use some local variables; therefore, this
 * is taken care of already.
 */
   printf("Positive Integers and String\n");
   cPtr->varInt = 32767;       // refer to member of struct and
   cPtr->varLong = 60000;      // assign values
   strcpy(cPtr->szString,"This is a test string");

   COBPROC ( cPtr);            // CALL to COBOL procedure

   printf("\n\n\n");

   printf("Negative Integers and String\n");
   cPtr->varInt = -32765;
   cPtr->varLong = -987654;
   strcpy(cPtr->szString,"Here's another string\n");

   COBPROC ( cPtr);
}

OUTPUT

Positive Integers and String
Integer from C: 2767
Long integer from C: 00060000
String from C: This is a test string



Negative Integers and String
Integer from C: 2765
Long integer from C: 00987654
String from C: Here's another string

The following sample code demonstrates how to pass an array of integers from COBOL to C.

INTARRAY.CBL

      * Passing an Array of Integers from COBOL to C
       data division.
       working-storage section.
       01 t-count pic 99.
       01 t-table.
          05 the-table pic 9(4) comp-5 occurs 5 times.
       procedure division.
       perform varying t-count from 1 by 1 until t-count > 5
       move t-count to the-table(t-count)
       end-perform.
       call "C_CProc" using t-table.
       stop run.

CNTARRAY.C

#include <stdio.h>
void CProc(int IntTable[4]) {
   int count;

   for (count = 0; count < 5; count++)
     printf("Array [%i]: %i\r\n", count, IntTable[count]);

}

OUTPUT

Array [0]: 1
Array [1]: 2
Array [2]: 3
Array [3]: 4
Array [4]: 5

The following sample code demonstrates how to pass a two-dimensional array of long integers from COBOL to C.

LINT.CBL

      * Passing long integers from COBOL to C
      $set bound
       data division.
       working-storage section.
       01 I1 pic 9.
       01 J1 pic 9.
       01 t-table.
          02 t-field occurs 2 times.
             05 the-table pic 9(8) comp-5 occurs 3 times.

       procedure division.
       perform varying I1 from 1 by 1 until I1 > 2
         perform varying J1 from 1 by 1 until J1 > 3
          move J1 to the-table(I1, J1)
         end-perform
       end-perform.
       call "_CProc" using t-table.
       stop run.

LINTC.C

#include <stdio.h>
void CProc(long IntTable[2][3]) {
   int i, j;

   for (i = 0; i < 2; i++)
      for (j = 0; j < 3; j++)
        printf("Array [%i,%i]: %ld\r\n", i, j, IntTable[i][j]);

}

OUTPUT

Array [0,0]: 1
Array [0,1]: 2
Array [0,2]: 3
Array [1,0]: 1
Array [1,1]: 2
Array [1,2]: 3

The following sample code demonstrates how to pass a two-dimensional array of records from C to COBOL

_COBPROC.CBL

       program-id. "_CobProc".
       data division.
       working-storage section.
       01 I1                          pic 9.
       01 J1                          pic 9.
       linkage section.
       01 the-table.
          02 t-table occurs 2 times.
             05 t-field occurs 3 times.
                10 field1             pic 9(4) comp-5.
                10 field2             pic x(6).

       procedure division using the-table.

       perform varying I1 from 1 by 1 until I1 > 2
          perform varying J1 from 1 by 1 until J1 > 3
             display "table[" I1 "][" J1 "]: " field1(I1, J1)
             display "             " field2(I1, J1)
          end-perform
       end-perform.
       stop run.

2DRECS.C

#include <stdio.h>

struct TableStruc {    /* define structure */
         int TheInt;
         char String[6];
       } TheTable[2][3];

extern void far cdecl CobProc(struct TableStruc TheTable[2][3]);

void main() {
   int i, j;

   for (i = 0; i < 2; i++)        /* initialize structure */
      for (j = 0; j < 3; j++) {
        TheTable[i][j].TheInt = j;
        Sprintf(TheTable[i][j].String, "[%1i][%1i]", i, j);
      }

   CobProc(TheTable);             /* CALL COBOL routine */
}

OUTPUT

table[1][1]: 00000
             [0][0]
table[1][2]: 00001
             [0][1]
table[1][3]: 00002
             [0][2]
table[2][1]: 00000
             [1][0]
table[2][2]: 00001
             [1][1]
table[2][3]: 00002
             [1][2]

The following sample code demonstrates how to pass integers by reference from COBOL to  C.

COBINT.CBL

      * Passing integers by reference from COBOL to C 
       working-storage section.
       01 passvar1 pic 9(4) comp-5 value 16384.
       01 passvar2 pic 9(4) comp-5 value 33.
       procedure division.
       display "Before the call to the C swapping function...".
       display "Passvar1 is equal to: " passvar1.
       display "Passvar2 is equal to: " passvar2.

       call "_SwapFunc" using by reference passvar1
                              by reference passvar2.

       display "After the call to the C swapping function...".
       display "Passvar1 is equal to: " passvar1.
       display "Passvar2 is equal to: " passvar2.
       stop run.

CINT.C

/* Manipulates integers passed from a COBOL program */
#include <stdio.h>

void SwapFunc(int *var1, int *var2)
   {
        int tmp;      /* Temporary value for use in swap */

        tmp = *var1;
        *var1 = *var2;
        *var2 = tmp;
        return;
   }

OUTPUT

Before the call to the C swapping function...
PassVar1 is equal to: 16384
PassVar2 is equal to: 00033
After the call to the C swapping function...
PassVar1 is equal to: 00033
PassVar2 is equal to: 16384

The following sample code demonstrates how to pass an integer from COBOL to C.

CBLINT.CBL

      working-storage section.
          01 pass-var pic 9(4) comp-5 value 3.

       procedure division.
       call "_Circum" using by value pass-var.
       display "Radius of circle: " pass-var.
       display "Circumference of circle: " return-code.
       stop run.

C.C

#include <stdio.h>

int Circum(int Radius) {
    float cir;
    cir = 3.14159 * Radius * Radius;
    return((int) cir);
}

OUTPUT

Radius of circle: 00003
Circumference of circle: +0028

The following sample code demonstrates passing a long integer from COBOL to C.

LINT.CBL

    $set rtncode-size(2)
       working-storage section.
       01 pass-var pic 9(4) comp-5.

       procedure division.
       display "Radius of circle?".
       accept pass-var.
       call "_Area" using by value pass-var.
       display "Area of circle: " return-code.
       stop run.

LINTC.C

#include <stdio.h>
long Area(int Radius) {
    float cir;
    cir = 3.14159 * Radius * Radius;
    return((long) cir);
}

OUTPUT

Radius of circle?
1
Area of circle: +0003

The following sample code demonstrates how to pass a string from COBOL to C.

COBSTR.CBL

      * Passing a string from COBOL to C
       identification division.
       program-id. cobstr.
       data division.
       working-storage section.
       01 passvar pic x(15) value "Replace this".
       procedure division.
         display "This is what is passed: " passvar.
         call "_Funct" using pass-var.
         display "This is what comes back: " passvar.
         stop run.

CSTR.C

#include <ctype.h>

void * Funct(char *Rvalue)
   {
    char *cp;
    cp = Rvalue;
    while (*cp != '\0') {
       *cp = toupper(*cp);
       ++cp;
    }
    return;
   }

OUTPUT

This is what is passed: Replace this
This is what comes back: REPLACE THIS

The following samples demonstrate how to call a C 6.x routine from a COBOL 4.5 program, where the C function, in turn, spawns another COBOL 4.5 executable.

Note: The COBOL program titled COB2.CBL must be compiled and linked as a stand-alone executable module. Use the following lines to compile and link this program:

   COBOL COB2;
   LINK COB2,,,LCOBOL COBAPI/NOE/NOD;

MAIN.CBL

      * How to call a C function that executes another COBOL 
      * program.
       program-id.     main.
       working-storage section.
       01 commandL.
          05  filler          pic x(01)  value 'S'.
          05  cmdlin          pic x(124) value "COB2.EXE".
       procedure division.
       display "In COBOL program 1".
       call "_pcexec" using commandL.
       display "End of COBOL program 1".
       stop run.

PCEXEC.C

#include <stdio.h>
#include <process.h>
pcexec (commandL)
char far commandL[125];
{
     printf ("Prior to C call of COB2.EXE \n");
     spawnl (P_WAIT, "COB2.EXE", "COB2", "spawnl", NULL);
     printf("After C call to COB2.EXE \n");
}

COB2.CBL

      * This program must be a separate executable.
       program-id.     cob2.
       procedure division.
        display "Inside COBOL program 2".
       stop run.

OUTPUT

In COBOL program 1
Prior to C call of COB2.EXE
Inside COBOL program 2
After C call to COB2.EXE
End of COBOL program 1

The following samples demonstrate how a COBOL 4.5 Quickwin application can call a Windows™-based DLL written in C 6.x.

MAIN.CBL

       working-storage section.
       77 Var1                  pic 9(4) comp-5.
       77 Char                  pic x.
       procedure division.
       move 1 to Var1.
       display "Prior to DLL call: " at 0101
       display Var1 at 0120.
       call 'cdll' using by reference Var1.
       display "After DLL call: " at 0201.
       display Var1 at 0217.
       call "cbl_read_kbd_char" using Char.
       stop run.

MAIN.DEF

EXETYPE         WINDOWS 3.0
APPLOADER       '__MSLANGLOAD'
PROTMODE
STUB            'WINSTUB.EXE'
CODE            PRELOAD FIXED
DATA            PRELOAD FIXED MULTIPLE
STACKSIZE       16384
HEAPSIZE        1024
EXPORTS         WNDPROC

CDLL.C

#include <windows.h>
int FAR PASCAL LibMain(HANDLE hInstance,
                        WORD  wDataSeg,
                        WORD  cbHeapSize,
                        LPSTR lpszCmdLine)
{
//Additional DLL initialization fits here
if (cbHeapSize != 0)
    UnlockData(0);
return (1);
}

VOID FAR PASCAL cdll(int _far *piIntPointer)
{
if((*piIntPointer >= -32768) && (*piIntPointer < 32767))
   {
      (*piIntPointer)++;
         return(1);
   }
else
   {
         return(0);
   }
}

VOID FAR PASCAL WEP (int nParameter)
{
if (nParameter == WEP_SYSTEM_EXIT)
   {
   return (1);
   }
else
   { if (nParameter == WEP_FREE_DLL)
      {
      return (1);
      }
    else   {
       return (1);
           }
    }
}

CDLL.DEF

LIBRARY         cdll
DESCRIPTION     'C DLL FOR WINDOWS 3.0'
EXETYPE         WINDOWS
STUB            'WINSTUB.EXE'
CODE            PRELOAD MOVEABLE DISCARDABLE
DATA            PRELOAD MOVEABLE SINGLE
HEAPSIZE        0
EXPORTS         Cdll    @1
                WEP     @2 RESIDENTNAME