You are on page 1of 12

DEMO1.TXT (NetExpress 3.

Wednesday, December 9, 1998, 8:06AM
These are the original notes distributed with the 3.2.50 version of
Demo1. In the transition from 16bit to 32bit these programs have been
successfully executed with Visual Object COBOL, Workbench 4.0,
NetExpress 1.0 and 2.0. There were a few minor changes made to the
source to get things to work correctly in the process. It is a future
intention to restore the source code to the original developed with
Using the contents of the Zip file
---------------------------------Mixed Language Programming isn't always as "slick" as Off Loading. Some
compromises must be accepted to be successful. How to proceed.
1) Start a NetExpress Command Line.
2) Create an empty directory.
3) Change into the empty directory.
4) Unzip the VB5D1NX3.ZIP file into the new directory.
5) Execute DOIT.BAT to compile and link the COBOL programs.
6) Type DEMO1.EXE<Enter> to execute the example. The Visual Basic Run
time files are included so the example should execute even if Visual
Basic hasn't been installed. Click the various buttons in the example
until you get bored with it. Then Click the Quit button to terminate
the example. The various Message Box displays you'll see show
information about the parameters being received and returned by the
COBOL programs and progress through the Dlls for the file handling
7) Go to the Windows Desktop (don't close the NetExpress Command Line).
Using Find, determine the drive and path to where your Visual Basic 5
executable (VB5.EXE) is located (drive:\path\VB5.EXE).
8) Return to the NetExpress Command Line (back to where we were in step
six). Type drive:\path\VB5.EXE<Enter>. This should start Visual Basic.
Open the Demo1 project and Debug the Visual Basic application. This
will provide you an opportunity to view the comments in the Visual
Basic code and see the Message Boxes from the COBOL programs, again.
9) When you tire of Visual Basic, terminate it and from the Command
line type Mfnetx.exe<Enter>. This will start NetExpress within this
directory. Create a New Project named Demo1. Start by populating the
project with Demo1.exe, Msvbvm50.dll and Oleaut32.dll. Then add
Coboldll.cbl to the project, selecting object code and packaging as a
Dll. All the Dlls should be packaged this way. The Build settings for
this Dll need to be custumized to keep the temporary linker files.
Select the Advanced Category on the Link Tab in Build Settings and
check the Check box fo Keep temporary link files. Next add Coboldl2 to
the project. This Dll requires a graphical setting. You'll need to add
a -g switch setting to the Cbllink Directives on the Link tab in the
Advanced Category. Next add Coboldl3 and Coboldl4. Both of these Dlls
need the Include System Files check box unchecked. This check box is on
the Link Tab in Build settings, Category Advanced. They also need
access to the Coboldll.lib file. This is also on the Link Tab, Advanced
Category. Just type the library name, preceded by the drive:\path where
the Lib file is located, into the text window. The remaining Dlls,
Coboldl5, Coboldl6 and Coboldl7 do not require any special settings.
Now that everything is setup, you can do a Rebuild All from the Project

Menu. What should be the result of the Rebuild All is that all the
Cobol Dlls and the Visual Basic programs end up in the Debug directory.
You can confirm this by openning the original prompt from your TaskBar
(never hide the TaskBar, it is just too handy to have hidden). What's
definitely going to be missing is the data file, which is an indexed
file, so either manually copy these files (Idxfile.dat, Idxfile.idx)
into the Debug directory. If you don't copy these files, you will find
out what happens when the files are missing. (You can do both, try one
of the file handling buttons with no files, then copy them over, and
try it again.) (Now, right mouse Click on Demo1.exe and Click Animate.
Click Browse, and see if there is a Debug directory visible. If there
is, open this directory and select Demo1.exe. The VB Application should
start and when you click on one of the buttons the Animator should show
you the source for the Cobol programs. While you are Animating the
Cobol programs you can read the comments, but more importantly you can
examine the parameters coming from Visual Basic in the linkage section.
All this is pretty neat, but remember, this Application has already
been debugged. When errors occur debugging a program that is wrong,
expect to have to Reboot, on occasion.
10) There is one last Rabbit to pull out of the hat. This one is not
recommended for the feint of heart, and will definitely recquire a
reboot when things get a little confused. Additional preparatory file
copying is needed. The Visual Basic Application files (Initial.frm,
Initial.frx, Vbcobol.bas, Demo1.mak, Demo1.vbw) need to be copied into
the Debug directory. Right mouse Click on Demo1.exe. Get into the Debug
directory and select Demo1.exe as before. When you are looking at the
"Start Animating" dialog, highlight drive:\path\Demo1.exe, and type
drive:\path\VB5.EXE in it's place. Visual Basic should come up and you
can load the project and start debugging. When a call is made to a
Cobol program, the Animator will come up and show you the Cobol
program. You will need an uncluttered TaskBar for this as the programs
involved don't always bring themselves to the front. Also, Demo1 will
work because it has been through this process. Your program, on the
other hand, being it's usual mess, isn't likely to behave quite so
well. Expect the need for Reboots. Also, turn off the CD-Rom music and
anything else that you might have running. You need all the resources
and patience available to make this go smoothly. Good Luck!
A few words about the Batch files. Createnv.bat is an example Batch
file for setting up the SDK environment and then setting the NetExpress
environment. It isn't going to work anywhere but on my machine. Just
note that there is a Batch file that comes with the SDK and it will set
up the environment variables needed. Also note that there is a program
you can run in the NetExpress Bin directory that will set up a Batch
file you can run that will inherit whet is set up for the SDK. End of
Doit.bat is the Batch file used to compile and link the Cobol programs
in this example. Make note of the switches used. There is only one
graphic program in this example. It's the program that calls
MessageBox. Also note that two Dlls require the -s switch to keep the
file handler out of these programs. The file handler is in Coboldll.dll
and you don't want multiple copies of the file handler in your
application. An alternative to this approach would be to keep the file
handler out of all the Dlls, and make Mffh.dll available. That's it.
Friday, March 28, 1997, 9:11AM

Only run this example under 16bit Windows. Use VB3D132B.ZIP if you want
run this example under 32bit Windows.
10/13/96 3:05PM Micro Focus 3.2.50 and Visual Basic 3.0 Professional
Only run this example using Micro Focus V3.2.50. Earlier Update levels
do not
fully support this example.
Demo1 addresses Interfacing Visual Basic and COBOL. As such it only
illustrates technical details.

The Files
--------It takes a lot of files to bake this particular cake. I have grouped
into categories that, hopefully, are meaningful.
The Visual Basic Files
---------------------I'm not a sophisticated Visual Basic Programmer, so don't look for
very fancy here.
- The Project Make FIle for Demo1
INITIALF.FRM - The Initial (and only) Form for Demo1
VBCOBOL.BAS - The Global Declarations for Demo1
The COBOL Files
--------------Three very helpful Micro Focus extensions were used in the creation of
Demo1, External Programs, TYPEDEFs and Level 78 items. An External
Program provides the compiler with specification details that permit
the verification of each call statement parameter picture and usage,
determines whether parameters are passed by value or reference and sets
the call convention. TYPEDEFs permit specification of data items and
records in your program consistent with items and structures defined in
a Visual Basic program or a 'C' header file. Level 78 items permit the
definition of constant values that can then be referenced symbolically.
The Language Reference Manual, Issue 14, documents External Programs on
page 4-3, TYPEDEFs on page 4-140 and Level 78 items on page 4-97.
Use copy statements to submit External Programs to the compiler. Their
symbol definitions will be stored by the compiler, the programs will
not be compiled. Your program must follow the copy statements for any
External Programs you are using and begin with an Identification
Division header, distinguishing it from the External Programs. It will
be compiled using the stored symbols and any symbols defined in your
program. CALLCONV and VBTYPES are rather simple External Programs,
serving specific objectives. The MSGBOX External Program is a complete

MessageBox Api

An External Program defining call conventions

An External Program defining the Windows 16bit
An External Program defining Visual Basic Data Types
The Interface Example Program
The Windows Api MessageBox Handler
A Separate File Handling Example
A self-contained File Handling Example
A Pass-Through Example
A Straight COBOL Example
A Test Program to evaluate The Currency Data Type Problem

Compiling and Linking Files

--------------------------I create Batch files to ensure repeatability. I start from the command
line, eventually echoing my command line (I also use Doskey) into a
Batch file. I use the compiler to create the Link Definition (def)
file, and echo Imports into the def file. Once the Link is correct
(from the command line), it gets echoed into the Batch file as well and
the laundry list of module names, DLL name, library names,and def file
name get clipped into a Link Response file (rsp). This makes it easy to
repeat the process and, I hope, easier for the reader to understand
what is going on.
Linking DLL

- Batch File for Compiling, Annotating DEF Files and

- Link Definition File
- Link Response FIle

Data Files
---------These are very simple files, created and tested with the Animator. This
makes it possible to perfect the select and FD statements independent
of the program(s) that need them. These statements are good candidates
for a copy book since they may be replicated many times in different
programs. I haven't done this as the definitions are simple and I
wanted to keep the example programs complete for reading ease.

- Data portion of indexed file

- Index portion of indexed file

DLL Files
--------The following describes each of the entry points within each DLL. The
focus is on the processing accomplished.

COBOLDLL Entry Points

--------------------I've used the Windows MessageBox Api to track DLL processing.
to the Api is in the COBOLDL2 DLL. Unfortunately, the details
message preparation may confuse the illustration a little. It
effective when you Debug Demo1 and see the elements passed to
returned by each entry point.

The call
is most

-------Each COBOL DLL's initial entry point (ordinal 1) begins after the
Procedure Division header. Other examples use this entry point, but not
this one. "Just in Case," I've coded an exit program statement after
the Procedure Division header. If this entry point gets called by
accident, I don't want to "fall" into the GETINTSB routine. For further
insurance I've coded a stop run statement. I suppose this is a matter
of style more than anything else, but these statements make it clear to
me that nothing happens if you call this DLL by name.
-------The GETINTSB entry point shows you how to code a COBOL program that you
want to call from Visual Basic as a subroutine. Two Integers are passed
to COBOL from Visual Basic by reference. The entry point updates the
variables and returns control to Visual Basic.
A Visual Basic Subroutine call is coded in a style a COBOL programmer
should find familiar:
Call GETINTSB(p1, p2) ... .
Small differences, but a similar overall structure. The subroutine name
isn't a non numeric literal, parameters are grouped by parenthesis
instead of a using clause, and a comma must separate adjacent
The Visual Basic Declare statement for the call provides the details,
reference, by value and data types:
Declare Sub GETINTSB Lib "coboldll" (p1 As Integer, p2 As
Integer) ... .
Visual Basic's default is to pass items by reference, the same as
COBOL's entry statement matches Visual Basic's Declare statement in
terms of the number and position of parameters:
entry 'GETINTSB' Pascal using p1, p2. ... .
Calling convention can be omitted if coded as part of the Procedure
Division header, in which case it applies to every entry statement.
Commas separating parameters is optional in COBOL. A subroutine returns
no value.
-------The FDLINTFN entry point shows you how to code a COBOL program that you

want to call from Visual Basic as a function. An Integer and a fixed

length String are passed by reference from Visual Basic to COBOL. The
entry point uses the Integer as data, updates the fixed length String,
and returns a function status code to Visual Basic.
A Visual Basic Function call is coded in a style more familiar to 'C'
programmers than COBOL programmers:
If FDLINTFN(p1, p2) ... ; or
worked = FDLINTFN(P1, P2) ... .
In the above, two examples are presented. The first tests the return
value of the function call immediately. When using this technique, the
return value is not captured by the calling program. The second example
captures the value in a variable. The variable can then be tested
independent of the actual call and retained for later reference.
The Visual Basic Declare statement for the call provides the details:
Declare Function FDLINTFN Lib "coboldll" (p1 As Integer, p2 As UDF)
Integer ... .
Note the trailing type definition, it defines the type for the return
value. Also note, the second parameter does not have a standard Visual
Basic Type.
FDLINTFN accepts a fixed length String by reference. Visual Basic
doesn't permit passing a fixed length String variable by reference.
(See the FXLNSTRF entry point discussed below.) You must "hide" the
fixed length String in a User Defined Type in order to pass it by
reference. The following illustrates how to define a new type
consisting of a standard type.
Type UDF
fixedString As String * 5
End Type
In addition to the above, which only defines the new Type, you must
declare a variable of this Type.
Global p2 As UDF
It is the declaration of the variable that you reference in your Visual
Basic Function Call, not the declaration of the Type.
The return value gets back to Visual Basic via the exit program
statement terminating the Function.
exit program returning functionStatus.
The functionStatus field is defined in the COBOL program's WorkingStorage Section. It should be an Integer to match the specification in
the Visual Basic Declare for the Function. Return a value of -1 (True)
if the Function processing is successful, a value of 0 (False) if
-------This Function receives one parameter, a Visual Basic Currency item,
passed by reference. Currency items are likely to be of greatest value
when returning data to Visual Basic. Passing a Currency item to COBOL
presents a problem in that the actual maximum value for a Basic item is
greater than can be defined in an equivalent COBOL item. Other than
this detail there isn't anything very

novel about Currency items. (Most likely, you will picture edit your
items in COBOL and return the edited value to Visual Basic as a
-------Two parameters are passed to this function, an Integer passed by value,
and a String passed by reference. An odd aspect of the String item
requires you to specify ByVal in the Declare for the Function to get a
far pointer.
Declare Function FDLSTRFN Lib "coboldll.dll" (ByVal p1 As Integer,
p2 As String) As Integer
The declaration specifies that the String variable is passed by value.
A far pointer to the location of the String in Visual Basic's memory is
what gets passed. The actual String value is a null terminated series
of characters.
To ensure that the your program doesn't overlay the null character, or
spoil an adjacent area of unknown content, pass the current length of a
String as a separate item. Visual Basic needs the null to manipulate
the String. The Len (length) operator always reflects the current
length of a String variable.
-------This Function receives two parameters, an Integer, and a Fixed Length
String. Again, this is a little odd. The Declare specifies ByVal (by
value) for both items.
Declare Function FXLNSTRF Lib "coboldll.dll" (ByVal p1 As Integer,
p2 As String) As Integer
The Fixed Length String must be defined as such.
Global p2 As String * 5
The result is the same as in FDLSTRFN, a far pointer to the String
item. The actual String value is a null terminated series of
Just as with the variable length String, passing the length may be
useful. Unlike a variable length String, a Fixed Length String's length
is constant, regardless of how many non space characters make up the
current value.
Note: Perhaps I didn't read the MS Documentation correctly. I believed
this couldn't be done. I found two independent sources that said it
could, so I've included an example. Perhaps MS meant that if you pass a
fixed length String by value, what is received is a far pointer to a
null terminated String.
-------This is a subroutine. No parameters are passed. It demonstrates basic
file processing, Open the file, access a record, close the file and
return. You must close the file before returning to Visual Basic.
Failure to close the file will cause a subsequent call to the program
to fail. It will also keep the file locked so that it cannot be

accessed by other programs.

-------This is a subroutine. No parameters are passed. It illustrates a "pass
thru" (transfer of control), to an entry point in another DLL. The
other DLL, is a copy of the code in the previous entry point, CBLDLLEP.
The call convention is static. Because we are calling a DLL linked with
EXTFH, we must use a static call. You cannot cancel a DLL linked with
EXTFH. Making a static call eliminates the need to cancel the called
COBOLDL2 Entry Points
--------------------COBOLDL2 is the DLL that makes all the Windows Api calls to MessageBox.
The MSGBOX.EXT, External Program was created using output produced by
H2CPY. The EXT file extension distinguishes this file from a true COBOL
program. The MessageBox Api is described below.
-------This entry point receives one parameter, the text to be displayed. This
is a small program. The details are in the External Program,
COBOLDL3 Entry Points
--------------------All the code in this program is from COBOLDLL. The only changes are to
literal values and names.
-------The purpose here is to illustrate that you can call a DLL from Visual
Basic, and then call another file processing DLL. This entry point will
also call COBOLDL2 to accomplish the MessageBox displays, which takes
us into another DLL supplied by Windows. That makes us four deep on
DLLs! Wow!
COBOLDL4 Entry Points
-------This DLL has only one entry point. It exemplifies a monolithic COBOL
program. Two purposes are served here. First, we are calling a second
COBOL DLL from Visual Basic (the limitation is available memory).
Second, this DLL executes and returns to its caller when finished.You
must ensure the program ends with an exit program statement. If you
execute a stop run in a COBOL DLL, Visual Basic, COBOL and Windows are
going to be very confused!
COBOLDL5 Entry Points
-------COBOLDL5 has only one entry point. Ignoring the MessageBox processing,

this program does little. It calls COBOLDL6 by DLL name. It calls an

entry point in COBOLDL6 (CBLDL6EP). And it cancels COBOLDL6. No call
convention is used for the COBOLDL6 calls! The COBOL call convention is
being used.
Three objectives are served by this example. First, we are loading
COBOLDL6 dynamically. That's what happens when you call a COBOL DLL by
its name. Any entry points in the DLL are exposed and we are then able
to call these entry points dynamically. If you call a COBOL DLL
dynamically you must cancel that DLL. Previously, our DLL navigation
has been done with static calls, and to satisfy the link program we've
had to supplement the Def file with Imports statements. You won't find
any Imports statement in DOIT.BAT for COBOLDL6.
Second objective. We are "bridging" the call convention gap! Visual
Basic uses the Pascal call convention. COBOLDL5 calls COBOLDL6 with a
standard COBOL call convention. That means the call convention in
COBOLDL6 does not need to be changed, assuming it is an existing
"Legacy" application.
Third objective. We are "bridging" the data definition gap! Although
demonstrated, COBOLDL5 is the ideal place to convert those pesky Visual
Basic data types into "Legacy" data types before passing them to
COBOLDL6. Again, this eliminates the need to make changes to COBOLDL6.
Important Note: You will notice that the Button for COBOLDL5 is
disabled when you start Demo1. This is because EXTFH is not linked into
COBOLDL5. When file processing is a function of your application, EXTFH
must be linked into the first COBOL DLL called from Visual Basic. Once
Demo1 loads any of the other DLLs, the button for COBOLDL5 is enabled.
See the Program Structure below.
COBOLDL6 Entry Points
-------A use, beyond exit program, has been found for this entry point. I'm
updating the messageBox string. COBOLDL6 doesn't call COBOLDL2 to
display messages. COBOLDL5 actually displays the messages from
-------I had to do something in here, so in addition to updating the
string, I called COBOLDL3 to illustrate that file processing can be

Windows Control Icon, or System Menu Icon

----------------------------------------This icon appears in the upper left Window corner. It drops a Menu with
a Close Button. Clicking this Button ends your Visual Basic
Application. You can suppress the System Menu Icon by changing the

ControlBox Property in your Form. When I started this project I had

difficulty with this Close button. It wasn't recognized by my COBOL
programs. This has been repaired in 3.2.50. You might need to disable
this icon to control user behavior, ie. Quit using only the Quit button
provided. Your application may have a good reason to require that kind
of behavior.

Visual Basic is "Event Sensitive"

--------------------------------Keep in mind that Visual Basic is an "event sensitive" application.
When you click a button something happens. If you double click the same
button, that something happens twice. Your COBOL Run Time is not "event
sensitive" (there is some jargon that applies here, multi-threading,
which is not supported by the 16bit Run Time). What are the
consequences combining these significantly different systems?
Accidents! What is an accident? Remember that people are going to use
your application. People, as we all know, but tend to overlook, have
many little accidents. Double clicking a control that results in a call
to a COBOL DLL can create havoc (ie. an accident!). A second call to
the DLL
could result before the DLL has completed processing the first call.
Needless to say, the DLL and the Run Time are unprepared for this type
of event. The precaution you must take is disabling your controls
before making a call to your COBOL DLL, and then enabling your controls
when the call is completed. Two sub procedures, DisableAllControls and
EnableAllControls, have been added to Demo1 to aid in the prevention of
accidents. Safety First!

Windows MessageBox Api

---------------------It's a tradition of long standing that display statements are used in
the debugging of COBOL programs. 'C' programmers use fprint, but seldom
admit to it. Under Windows both use the MessageBox Api. Below is the
COBOL you need to know in order to call MessageBox and display a
character string.
call-convention 11 is staticPascal.
working-storage section.
pic 9(4)
comp-5 value 0.
pic x(n)
value '...' & x'00'.
pic x(n)
value '...' & x'00'.
pic 9(4)
comp-5 value 64.
pic s9(4)
procedure division.
call staticPascal 'MessageBox' using by value
by reference mBText,
by reference mBTitle,
by value
Hwnd is your Window handle and is an unsigned integer. If you don't

have a handle handy (Hah), you can use a null (0). Text is the data you
want to display. It is a null terminated string. If the data you want
to display is numeric and a non display usage, move the data to an
edited numeric field terminated with a null. Title is what will appear
in the Title Bar of your MessageBox popup. It is also a null terminated
string. Style determines what buttons your popup will have, a null
value will get you an OK button. The value shown will get you that
lower case "i" in a blue circle, which stands for "information," and an
OK button. Return is an integer and is the return value for the
MessageBox. You can test Return to see if it worked, but then you'll
probably see the MessageBox anyway, so I don't know how valuable the
test might be. The above is included for those who are not quite ready
External Programs.

The Calling/Called Program Structure of Demo1.

---------------------------------------------The following is the best I could come up with as a way of summarizing
the "calling/called" program structure of Demo1. Each COBOL DLL has an
initial entry point (ordinal 1) with the same name as the DLL. This
entry point is implied in COBOL and exists immediately following the
Procedure Division header or the Declaratives, if present.
The general form of the entries is:
as in an IMPORTS statement. Transfer from one program to another is
expressed as follows:
where call-type is either static (s) or dynamic (d). Bit 3 of callconvention is set (value 8) for a static call and not set (value 0) for
a dynamic call. Wherever EXTFH is linked into a DLL I've noted its
inclusion as +XFH following the DLL name:
Since COBOLDL2 always/only calls the MessageBox Api, I've noted that
only once to reduce the complexity. To get everything to fit, I have
abbreviated the DLL names as follows:
Following Demo1 Calling/Called Program Structure I've noted the 3.2.50
call-type definitions.
Demo1 Calling/Called Program Structure

cancel COBOLDL6
Call Type Definitions
--------------------A COBOL DLL can be called dynamic.
A COBOL DLL called dynamic must be canceled by the program making the
Entry points in dynamically called COBOL DLLs must also be called
Do not cancel entry points.
A COBOL DLL can be called static.
Do not cancel a COBOL DLL called static.
Entry points in static called COBOL DLL must also be called static.
Do not cancel entry points.
EXTFH, if required in any part of the application, must be linked into
the first COBOL DLL called from Visual Basic.
EXTFH must be linked into every DLL requiring its file handling
You cannot cancel a DLL containing EXTFH.
You must call static a DLL containing EXTFH.
Call Type Table
--------------EXTFH Linked? - DLL Call Type - Entry Point Call Type - Cancel DLL?

That's it for Demo1. I hope the information is useful.

Wed, Sep 18, 1996, 11:20 AM
Friday, March 28, 1997, 9:11AM