Multiple app debugging

Real life projects are large in size and may consist of several sub-projects. It is essential that an IDE allows debugging of large apps spanning across several projects. With Code::Blocks we can do it easily.

To learn multiple app debugging we'll create two projects—first project a DLL project and second one is a console project that depends upon first DLL project. Then save both projects under same workspace named App8.

Go to File | New | Project | Dynamic Link Library menu option to create a DLL project. Name this project libobject. Now rename the libobject project files. We'll rename main.h file to dllmain.h and main.cpp to dllmain.cpp file. To do this, close all open editor files and right-click on the file name in the project tree as shown in the following screenshot:

Multiple app debugging

Enter new file name in the dialog box shown in following screenshot:

Multiple app debugging

This will avoid ambiguities in file names. Now replace code inside dllmain.h file with the following code.

#ifndef __DLLMAIN_H__
#define __DLLMAIN_H__

/*  To use this exported function of dll, include this header
 *  in your project.
 */

#ifdef BUILD_DLL
    #define DLL_IMP_EXPORT __declspec(dllexport)
#else
    #define DLL_IMP_EXPORT __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C"
{
#endif
    void DLL_IMP_EXPORT SayHello(void);
#ifdef __cplusplus
}
#endif

class base {
public:
    void Set(int width, int height) {
        m_width  = width;
        m_height = height;
    }
    virtual int Area() = 0;
protected:
    int m_width, m_height;
};

class DLL_IMP_EXPORT Rectangle : public base {
public:
    int Area();
};

class DLL_IMP_EXPORT Triangle : public base {
public:
    int Area();
};

#endif // __DLLMAIN_H__

A DLL on Windows require special decoration in order to export it from a dynamic link library. This decoration statement changes while it is exported and at the time it is imported. Decoration __declspec(dllexport) is used to export functions from a DLL and __declspec(dllimport) is used to import function from another DLL. Decorations instruct linker to export or import a variable/function/object name with or without name mangling. A preprocessor define DLL_IMP_EXPORT is used to indicate compiler whether a function or a class is being exported or imported.

C++ allows function/method overloading. It is achieved by introducing name mangling in the generated code. Name mangling is a process in which a function name is converted to a unique name based on function parameters, return type, and other parameters. Name mangling is compiler dependent and as a result any DLL written is C++ can't be used directly with another compiler.

C++ introduces name mangling by default for all functions. We can stop name mangling using extern "C" keyword and are using it to stop name mangling for the exported SayHello() function. By stopping name mangling we can use a DLL written in C++ and compiled with one compiler to be used with another compiler.

We have defined a class base and this base class has a member function Set() and it sets two internal variables. There is a pure virtual function named Area() that must be redefined derived classes. A pure virtual function is a function that has not been implemented in the base class. If a pure virtual function is called in any app it may result in a crash.

However, this base class is not decorated with DLL_IMP_EXPORT. This means it will not be exported in DLL and no outside app can use this class.

In order to use feature of the base class we'll create two derived classes. Class Rectangle and Triangle, these are derived publicly from the base class. We have used inheritance of classes here. These classes are declared with decoration DLL_IMP_EXPORT. Thus these two classes will be exported in the resulting DLL.

Now replace code inside the dllmain.cpp file of the libobject project with the following code:

#include <windows.h>
#include <iostream>

#include "dllmain.h"

void SayHello(void) {
    std::cout << "Hello World!" << std::endl;
}

int Rectangle::Area() {
    return (m_width * m_height);
}

int Triangle::Area() {
    return (m_width * m_height / 2);
}

extern "C" DLL_IMP_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
    switch (fdwReason) {
        case DLL_PROCESS_ATTACH: // attach to process
            // return FALSE to fail DLL load
            break;
        case DLL_PROCESS_DETACH: // detach from process
            break;
        case DLL_THREAD_ATTACH: // attach to thread
            break;
        case DLL_THREAD_DETACH: // detach from thread
            break;
    }
    return TRUE; // successful
}

Code in the dllmain.cpp file mainly defines all the code of publicly exported function. There is a DllMain() function. It may be used to do any initialization or de-initialization for the DLL.

Next create a console app named App8. Now rename workspace as App8 and save workspace as App8. This console app will use functions defined in libobject.dll. Replace code inside the main.cpp file of App8 with the following code:

#include <iostream>

#include "dllmain.h"

int main() {
    Rectangle rect;
    rect.Set(10, 20);
    Triangle  trigl;
    trigl.Set(5, 6);
    std::cout << "Rectangle(10, 20).Area() = " << rect.Area() << std::endl;
    std::cout << "Triangle(5, 6).Area() = " << trigl.Area() << std::endl;
    return 0;
}

Next, we have to prepare our App8 project to use this DLL. To do so go to Project | Build options menu option. Select App8 in the project tree and then click on Search directories tab. Then add ..libobject directory to the list in the Compiler tab. This instructs compiler to search for header files in that directory:

Multiple app debugging

We also need to point linker to the directory where we have kept import library of libobject.dll file. To do so select the Debug target and click on the Search directories tab. Then click on the Linker tab and add ..libobjectinDebug folder to the list:

Multiple app debugging

We have to instruct linker to find references of symbols found in libobject.dll file. To do so click on the Linker settings tab and add libobject.a to the Link libraries list.

Multiple app debugging

We'll set up project dependencies in this step. Go to Project | Properties… menu option and then click on the Project dependencies… button. Click on the libobject and then click on the Close button. Finally click OK button to close the Project/targets options window. This completes preparation of the App8 console app.

Multiple app debugging

Now go to Build | Build workspace menu option. This will build the libobject project first and subsequently App8 will be compiled.

In order to learn debugging multiple projects we'll set breakpoints at the following line number:

  • Line number 11, 15, 19 in the dllmain.cpp file, libobject project
  • Line number 7, 9, 10, 12 in the main.cpp file, App8 project

Breakpoints can be verified from Breakpoints window shown in the following screenshot:

Multiple app debugging

Note that DLLs can't run as a standalone process and require a host application to load them into memory. In order to debug a DLL we have to debug the host application that loads and runs it. Alternatively we can specify a host application (in our case App8.exe) for debugging by navigating to Project | Set programs' arguments… menu option.

We'll use first approach and let our host app to load libobject.dll, then use it to debug both libobject.dll and App8.exe file. Ensure that App8 project is activated in the project tree and then click on the debug/continue button in debugger toolbar:

Multiple app debugging

In the preceding screenshot execution has stopped at line number 19 of the dllmain.cpp file. Whenever DllMain() is exported it becomes the first function to be called during the loading/unloading of any DLL. As a result execution stops there.

Loaded libraries window in the following screenshot confirms that libobject.dll has been loaded in memory and this library can be debugged:

Multiple app debugging

Click on the Continue button to continue. Execution will now pause at line number 7 of the main.cpp file.

Multiple app debugging

Click on the Continue button twice. Execution will stop at line number 10 of the main.cpp file as shown in the following screenshot:

Multiple app debugging

Click on the Continue button again and execution will stop at line number 11 of dllmain.cpp file.

Debugger is now debugging libobject project's source file, which is a separate project. If cursor is hovered m_height variable debugger will evaluate this variable and show its value.

Multiple app debugging

It is evident that we can debug both DLL project and console app project at the same time. Larger projects can be debugged using a similar method. With this example we conclude our multiple app debugging session. Click on the Stop button to stop debugging.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.221.133