01.05.2013 Views

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

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!