Debugging a project containing C and COBOL - Micro Focus
Debugging a project containing C and COBOL - Micro Focus
Debugging a project containing C and COBOL - Micro Focus
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
Mixed-Language <strong>Debugging</strong> of <strong>project</strong>s <strong>containing</strong> C <strong>and</strong> <strong>COBOL</strong><br />
Net Express <strong>and</strong> other <strong>Micro</strong> <strong>Focus</strong> software development tools offer a wide range of possibilities to<br />
construct <strong>COBOL</strong> <strong>project</strong>s. Of course, programs written in different languages like C can be added to such<br />
a <strong>project</strong>. However, if such a mixed language <strong>project</strong> is to be debugged with the <strong>Micro</strong> <strong>Focus</strong> Animator, as<br />
well as with the C debugger, several restrictions have to be taken into account when designing the <strong>project</strong>.<br />
If the <strong>project</strong> consists only of <strong>COBOL</strong> programs, it can be animated in INT, GNT <strong>and</strong> EXE/DLL forms with<br />
Net Express. If there are C modules, however, these C modules must be linked as an EXE or DLL. Here a<br />
decision has to be made. Shall the same EXE/DLLs contain both the C <strong>and</strong> <strong>COBOL</strong> objects or only objects<br />
from one language? Both are possible, but when an EXE or a DLL contains both, you can debug either<br />
the C functions or animate the <strong>COBOL</strong> programs.<br />
To enable real mixed language debugging, i.e. debugging C <strong>and</strong> <strong>COBOL</strong> on the same application execution<br />
requires a different design. All <strong>COBOL</strong> programs, which are desired to be debugged, must be compiled to<br />
INT format.<br />
How can C functions <strong>and</strong> <strong>COBOL</strong> programs interface each other?<br />
1 A C main program <strong>and</strong> <strong>COBOL</strong> subprograms (which themselves can call C subprograms, …)<br />
2 A <strong>COBOL</strong> main program, which call the C functions (which themselves can call <strong>COBOL</strong><br />
subprograms, …)<br />
The C programs/functions must be compiled <strong>and</strong> linked to EXEs or DLLs. But a C function cannot directly call<br />
a <strong>COBOL</strong> INT. An interface module is necessary, which is written in <strong>COBOL</strong> <strong>and</strong> compiled into an OBJ. This<br />
.OBJ can be placed into a separate DLL or linked together with the C functions into a single EXE or DLL.<br />
Within the following example, a separate DLL is used. This is an easier methodology to use.<br />
Before we look at the debugging, we have to know, how a call between C <strong>and</strong> <strong>COBOL</strong> can be<br />
executed.<br />
Calling C from <strong>COBOL</strong><br />
1. A <strong>COBOL</strong> INT program can call a C function, where the C function is linked into the DLL, after the DLL is<br />
loaded into memory. This load can be performed by a SET-Statement or by a CALL statement towards the<br />
name of the DLL. Afterwards the call can be executed.<br />
Special-Names.<br />
Call-Convention 520 is C-CALL.<br />
*> 520 = static link + upper/lower case like written<br />
Working-storage section.<br />
01 PP usage is Procedure-Pointer value NULL.<br />
SET PP to entry “C_DLL.dll ”.<br />
IF PP = NULL<br />
Display “ C_DLL.dll could not be loaded into memory ”<br />
Stop run<br />
End-IF.<br />
Call C-CALL “My_C_Function ” *> using ...<br />
2. The direct call of a C-function, i.e. without the “SET PP to entry …”, does work from <strong>COBOL</strong><br />
compiled to EXE/DLL, but not from an INT, which we need for debugging.<br />
Page 1 of 6
Calling <strong>COBOL</strong> from C<br />
For the opposite direction we have both possibilities, when calling a <strong>COBOL</strong> DLL, like the example<br />
“interface.DLL” mentioned above.<br />
1. The first possibility works in exactly the same way as the “Calling C from <strong>COBOL</strong>” from above <strong>and</strong> may<br />
look like this:<br />
#include <br />
#include // for printf<br />
void C_Function()<br />
{<br />
}<br />
HINSTANCE myhdl;<br />
FARPROC myproc;<br />
myhdl = LoadLibrary("Interface.dll");<br />
if(myhdl == 0) {<br />
}<br />
printf( “Interface.dll could not be loaded into memory “);<br />
exit(1);<br />
myproc = GetProcAddress(myhdl, "MY-<strong>COBOL</strong>-PROGRAM" );<br />
(*myproc)();<br />
2. The second possibility needs a LIB-file, which contains the export definitions of the <strong>COBOL</strong> .DLL. This<br />
LIB is constructed when by the linking process, but is normally removed by <strong>Micro</strong> <strong>Focus</strong>. If the LIB file is<br />
needed an option must be selected as follows.<br />
If CBLLINK is used to link to DLL, add “-k” as option:<br />
cbllink –d –k My-Cobol-Program.cbl<br />
will compile <strong>and</strong> link a <strong>COBOL</strong> program appropriately.<br />
If the Net Express IDE is used, right-click on the DLL, select “Build settings...”, chose the tab “Link” change<br />
the “category” to “advanced” <strong>and</strong> check the “Keep temporary Linker files”. After a rebuild of the <strong>project</strong>, the<br />
LIB file will remain in the debug (or release) directory.<br />
This LIB file must be specified when linking the C OBJ files resp. included into the C <strong>project</strong>. It enables the C<br />
functions to call directly a <strong>COBOL</strong> program.<br />
void C_Function()<br />
{<br />
}<br />
MY_<strong>COBOL</strong>_PROGRAM();<br />
Page 2 of 6
Constructing a sample application<br />
For the sample programs, I have use the IDE of Net Express 3.1 <strong>and</strong> <strong>Micro</strong>soft Visual C++ 6.0. Even the Net<br />
Express IDE can be used to trigger the compile of the C programs, if a C compiler is installed, for debugging<br />
C it is better to also construct a C <strong>project</strong>.<br />
Now, change the following default in the Net Express IDE: In “Animate”, “Settings...”, in “Mixed Language<br />
<strong>Debugging</strong>”, select “Enable mixed-language debugging <strong>and</strong> disable generated <strong>and</strong> linked code debugging”. If<br />
you forget this, this Visual C debugger will stop at an unexpected “int 3” assembly instruction. This is the<br />
debugger-interrupt, but it cannot be h<strong>and</strong>led by two debuggers simultaneous.<br />
1. In the following screenshot, my settings can be seen:<br />
Start Animating at: MSDEV.exe Comm<strong>and</strong>line Parameters: C<strong>and</strong><strong>COBOL</strong>.dsw<br />
MSDEV.EXE is the Visual Studio debugger; C<strong>and</strong><strong>COBOL</strong>.dsw is the Visual C <strong>project</strong> file. In my demo, I start<br />
the Visual Studio as the start program.<br />
2. Alternatively, the EXE of the C-<strong>project</strong> can be used to start the application, but this requires a coded<br />
breakpoint within the EXE. There will be a slight different behavior, when starting in <strong>project</strong>. See below.<br />
Page 3 of 6
With this knowledge we can start to construct the <strong>project</strong>s.<br />
C main program <strong>and</strong> <strong>COBOL</strong> subprograms<br />
This is the C main-program <strong>and</strong> must linked as an EXE. An inline assembler instruction _asm{ int 3 } can be<br />
used to invoke the debugger. Alternatively a DebugBreak()-Call can be programmed. However, the Debugger<br />
will stop paradoxically at the assembly level when using the WinApi function <strong>and</strong> will stop on C level when<br />
using the assembler function.<br />
main()<br />
{<br />
}<br />
_asm{ int 3 }<br />
COB_Sub_interface();<br />
This is the <strong>COBOL</strong> subprogram:<br />
Program-id. “COB-Sub ”<br />
Procedure Division.<br />
display "This is <strong>COBOL</strong>_Subprog".<br />
This is the interface, written in <strong>COBOL</strong>, <strong>and</strong> should be linked as a DLL.<br />
It uses the Call-Convention 512 for entries from C, which means “respect upper/lower case”.<br />
It does not use the main entrypoint, but defines the C-Interface for all additional entries.<br />
Page 4 of 6
It contains an ENTRY-statement for each <strong>COBOL</strong> program called by C.<br />
The Interface-module cannot be debugged by the animator. Display statements can be added if<br />
necessary.<br />
Program-id. Interface.<br />
special-names.<br />
call-convention 512 is C-<br />
Interface.<br />
local-storage section.<br />
*> enables the interface to<br />
be called recursively<br />
procedure division C-<br />
Interface.<br />
main.<br />
goback.<br />
Entries Section.<br />
Entry-1.<br />
Entry "COB_Sub_interface"<br />
call "COB_Sub". *> called by file name, not by Program-id.<br />
goback.<br />
<strong>COBOL</strong> main program <strong>and</strong> C subprograms<br />
The <strong>COBOL</strong> part is exactly the sample “Calling C from <strong>COBOL</strong>” like above, when the C_DLL.dll can be<br />
found via the PATH environment variable. Compile the <strong>COBOL</strong> as an INT.<br />
The C part may look like follows. The _asm{ int 3 } invokes the C Debugger. Compile the function with<br />
the C compiler. Don’t forget to export the function “My_C_Function” by a DEF file.<br />
void My_C_Function()<br />
{<br />
}<br />
_asm{ int 3 }<br />
printf( “in a C DLL\n ”);<br />
Invoking the <strong>COBOL</strong> Animator<br />
The <strong>COBOL</strong> animator can be started by:<br />
Starting the application form the Net Express IDE with function key F11<br />
A call “CBL_DEBUGBREAK”<br />
Setting a breakpoint with function key F9 <strong>and</strong> starting the program.<br />
Invoking the C debugger<br />
The C debugger can be started by:<br />
Starting the application from Visual Studio with function key F10 or F11<br />
A WinApi function DebugBreak();<br />
An inline assembler instruction _asm{ int3 }<br />
Setting a breakpoint with function key F9 <strong>and</strong> starting the program.<br />
Page 5 of 6
Preparing the attached demo for a test run<br />
Select here to download the set of demonstration files is attached to this article<br />
1 To run this demo it is necessary to have both Net Express 3.1 <strong>and</strong> Visual C++ installed on the<br />
computer. This demo ran with Visual Studio 6.0 (start program: MSDEV.exe) <strong>and</strong> with Visual Studio.NET<br />
(start program: DEVENV.exe).<br />
2 The demo was constructed in D:\Article\C<strong>and</strong><strong>COBOL</strong>, but it should also run from a different location.<br />
3 Start the Net Express IDE by clicking on the NE <strong>project</strong> file <strong>COBOL</strong><strong>and</strong>C.APP.<br />
4 Rebuild the Net Express <strong>project</strong> by Rebuild-All<br />
5 Start the Visual Studio by clicking on the VC <strong>project</strong> file: C<strong>and</strong><strong>COBOL</strong>.dsw. With Visual Studio .NET<br />
let Visual Studio convert the <strong>project</strong>.<br />
6 There are 2 <strong>project</strong>s within C<strong>and</strong><strong>COBOL</strong>.dsw. Rebuild both.<br />
7 Closed Visual Studio.<br />
Running the demo - part 1: C main program <strong>and</strong> <strong>COBOL</strong> subprograms<br />
1 If MSDEV.exe from Visual Studio 6.0 is not reachable by PATH, open the Animator – Settings <strong>and</strong><br />
either add the required PATH to the start program or change the start program to “debug\C<strong>and</strong><strong>COBOL</strong>.exe”<br />
like in the graphics above.<br />
2 Start the Net Express <strong>project</strong> by F11<br />
3 If you use Visual Studio as start program, you need to start the application again from Visual Studio.<br />
If you use the C<strong>and</strong><strong>COBOL</strong>.exe as start program, Visual C will stop at the debugger breakpoint with an error<br />
message in a similar style as the CBL-DEBUGBREAK message box, where you can chose to invoke the<br />
debugger.<br />
4 You can use to step with F10 through the application.<br />
5 The debugging session will switch several times between the C debugger <strong>and</strong> the <strong>COBOL</strong> animator.<br />
6 The last step from the C main function, it will call a <strong>COBOL</strong> program, which calls a C program, which<br />
calls a <strong>COBOL</strong> program. Any part can be debugged. Step by step. (This makes the interface.dll recursive;<br />
therefore it needs a local-storage section.)<br />
7 On this step, please leave the C-function C_in_DLL_with_Breakpoint with F5 (go). Pressing F10 here<br />
will debug the <strong>COBOL</strong> runtime on assembly level. Please set a breakpoint into<br />
C_in_DLL_calling_COB_Sub_Sub(), if you want to stop there again.<br />
Running the demo - part 2: <strong>COBOL</strong> main program with calls to C functions<br />
1 The demo-run above contains this already. Instead starting the demo with F11, start the demo with<br />
the program at COB_Sub_Complex.int. Click with the right mouse button on the left <strong>project</strong> site on this .int<br />
<strong>and</strong> chose “Animate”.<br />
2 Please leave the C-function C_in_DLL_with_Breakpoint with F5 (go). Pressing F10 here will debug<br />
the <strong>COBOL</strong> runtime on assembly level. Please set a breakpoint into C_in_DLL_calling_COB_Sub_Sub(), if<br />
you want to stop there again.<br />
Page 6 of 6