Embedded software development is slowly moving towards object orientedanalysis, designand programming. The introduction of object oriented technologies in somesystems has not happened due to lack of C++ support on some platforms.
This article focuses on platforms where C++ compilers are not available. Thedevelopers working on these platforms should still be able to use objectoriented analysis and design. When it comes to final code development they canuse C.
The following sections cover an example of C++ code and its implementation inC.
- C++ Source Code: C++ source files implementing TerminalManager and Terminal classes.
- C Source Code: TerminalManager and Terminal implemented in C for a platform that does not support C++.
C++ Source Code
Terminal Manager and Terminal C++ header and source files are shownbelow:
Terminal Manager
TerminalManager.hpp
- // TerminalManager header file. We will be using this class
- // as an example for Object Oriented Programming in C.
- #include "Terminal.hpp"
- class TerminalManager
- {
- private:
- enum {MAX_TERMINALS=500};
- Terminal terminals[MAX_TERMINALS];
- Terminal *FindTerminal(int terminalId);
- public:
- TerminalManager();
- ~TerminalManager();
- void HandleMessage(Msg* pMsg);
- };
TerminalManager.cpp
- // TerminalManager source file. We will be using this class
- // as an example for Object Oriented Programming in C.
- #include <stdio.h>
- #include "TerminalManager.hpp"
- #include "Msg.hpp"
- TerminalManager::TerminalManager()
- {
- //...
- }
- TerminalManager::~TerminalManager()
- {
- }
- void TerminalManager::HandleMessage(Msg* pMsg)
- {
- int status, status1;
- int terminalId = pMsg->GetTerminalId();
- Terminal *pTerm = FindTerminal(terminalId);
- Terminal *pOtherTerm = NULL;
- if (pTerm != NULL)
- {
- switch (pMsg->GetType())
- {
- case CREATE_TERMINAL:
- pTerm->Activate((const TerminalCreateMsg *)pMsg);
- break;
- case DELETE_TERMINAL:
- pTerm->Deactivate((const TerminalDeleteMsg *) pMsg);
- break;
- case RUN_DIAGNOSTICS:
- status = pTerm->HandleRunDiagnostics((const RunDiagnosticsMsg *) pMsg);
- break;
- case PERFORM_SWITCHOVER:
- pOtherTerm = FindTerminal(pMsg->GetOtherTerminalId());
- status = pTerm->HandleOutOfService();
- status1 = pOtherTerm->HandleInService();
- break;
- }
- }
- delete pMsg;
- }
- Terminal *TerminalManager::FindTerminal(int terminalId)
- {
- if (terminalId < MAX_TERMINALS)
- {
- return (&terminals[terminalId]);
- }
- else
- {
- return NULL;
- }
- }
Terminal
Terminal.hpp
- // Terminal class header file.
- // Forward declaration for messages
- class TerminalCreateMsg;
- class TerminalDeleteMsg;
- class RunDiagnosticsMsg;
- class Msg;
- // Terminal class
- class Terminal
- {
- enum { UNKNOWN = 0 };
- enum {OUT_OF_SERVICE=1, INSERVICE=2};
- //...
- int terminalId;
- int terminalType;
- int terminalStatus;
- void SendMessage(Msg *pMsg);
- public:
- void Activate(const TerminalCreateMsg *pMsg);
- void Deactivate(const TerminalDeleteMsg *pMsg);
- int HandleRunDiagnostics(const RunDiagnosticsMsg *pMsg);
- int HandleOutOfService();
- int HandleInService();
- Terminal();
- ~Terminal();
- };
Terminal.cpp
- // Terminal class source file.
- #include "Terminal.hpp"
- #include "Msg.hpp"
- void Terminal::SendMessage(Msg *pMsg)
- {
- //...
- }
- Terminal::Terminal()
- {
- terminalId = UNKNOWN;
- terminalType = UNKNOWN;
- terminalStatus = UNKNOWN;
- }
- Terminal::~Terminal()
- {
- //...
- }
- int Terminal::HandleRunDiagnostics(const RunDiagnosticsMsg *pMsg)
- {
- int status = 1;
- //...
- return status;
- }
- int Terminal::HandleOutOfService()
- {
- int status = 1;
- terminalStatus = OUT_OF_SERVICE;
- //...
- return status;
- }
- int Terminal::HandleInService()
- {
- int status = 1;
- terminalStatus = INSERVICE;
- //...
- return status;
- }
- void Terminal::Activate(const TerminalCreateMsg *pMsg)
- {
- terminalId = pMsg->GetTerminalId();
- terminalType = pMsg->GetTerminalType();
- terminalStatus = pMsg->GetTerminalStatus();
- //...
- TerminalCreateAck *pAck = new TerminalCreateAck(terminalId, terminalStatus);
- SendMessage(pAck);
- }
- void Terminal::Deactivate(const TerminalDeleteMsg *pMsg)
- {
- //...
- terminalId = UNKNOWN;
- terminalType = UNKNOWN;
- terminalStatus = UNKNOWN;
- //...
- }
Msg.hpp
- // Messages used by the Terminal and TerminalManager classes.
- enum MsgType
- {
- CREATE_TERMINAL,
- DELETE_TERMINAL,
- RUN_DIAGNOSTICS,
- PERFORM_SWITCHOVER
- };
- class Msg
- {
- //...
- int msgType;
- int terminalType;
- int terminalId;
- int otherTerminalId;
- int terminalStatus;
- public:
- MsgType GetType() const;
- int GetTerminalId() const;
- int GetOtherTerminalId() const;
- int GetTerminalType() const;
- };
- // Message used to create a terminal
- class TerminalCreateMsg : public Msg
- {
- public:
- int GetTerminalStatus() const;
- };
- // Acknowledgement to Terminal Create message.
- class TerminalCreateAck : public Msg
- {
- public:
- TerminalCreateAck(int terminalId, int terminalStatus);
- };
- // Terminal Delete message
- class TerminalDeleteMsg : public Msg
- {
- };
C Source Code
Terminal Manager and Terminal C header and source files are shown below. Theimportant points to note are:
- Data members of a class map to C structures
- Methods of a class map to C functions with the "data member" structure pointer as the first parameter.
TerminalManager
TerminalManager.h
- /*
- TerminalManager header file. We will be using this class
- as an example for Object Oriented Programming in C.
- */
- #include "Terminal.h"
- #define MAX_TERMINALS 500
- /* Structure contains all data used by the Terminal Manager. */
- typedef struct
- {
- Terminal terminals[MAX_TERMINALS];
- } TerminalManager;
- /*
- ANSI C Function prototypes of all functions that operate
- on the TerminalManager structure.
- */
- void TerminalManager_Construct(TerminalManager *pMgr);
- void TerminalManager_Destroy(TerminalManager *pMgr);
- void TerminalManager_HandleMessage(TerminalManager *pMgr, Msg* pMsg);
TerminalManager.c
- /*
- TerminalManager source file. We will be using this class
- as an example for Object Oriented Programming in C.
- */
- #include <stdio.h>
- #include "TerminalManager.h"
- #include "Msg.h"
- #include <stdlib.h>
- Terminal *TerminalManager_FindTerminal(TerminalManager *pMgr, int terminalId)
- {
- if (terminalId < MAX_TERMINALS)
- {
- return (&(pMgr->terminals[terminalId]));
- }
- else
- {
- return NULL;
- }
- }
- void TerminalManager_Construct(TerminalManager *pMgr)
- {
- int i;
- /*
- C will not call construction functions, so loop through all call the
- construction functions for all terminals.
- */
- for (i=0; i < MAX_TERMINALS; i++)
- {
- Terminal_Construct(&(pMgr->terminals[i]));
- }
- }
- void TerminalManager_Destroy(TerminalManager *pMgr)
- {
- int i;
- /*
- C will not call destruction functions, so loop through all call the
- destruction functions for all terminals.
- */
- for (i=0; i < MAX_TERMINALS; i++)
- {
- Terminal_Destroy(&(pMgr->terminals[i]));
- }
- }
- void TerminalManager_HandleMessage(TerminalManager *pMgr, Msg* pMsg)
- {
- int status, status1;
- int terminalId = pMsg->terminalId;
- Terminal *pTerm = TerminalManager_FindTerminal(pMgr, terminalId);
- Terminal *pOtherTerm = NULL;
- /*
- Switch on the message type and invoke the Terminal's message handlers for
- the terminal specified in the message. Here the terminal manager takes
- care of indexing into the terminal structure and it passes the pointer
- to the terminal handler functions. Due to this design, implementation
- of the terminal handler functions just focus on handling the specified
- terminal.
- */
- if (pTerm != NULL)
- {
- switch (pMsg->msgType)
- {
- case CREATE_TERMINAL:
- Terminal_Activate(pTerm, (const TerminalCreateMsg *)pMsg);
- break;
- case DELETE_TERMINAL:
- Terminal_Deactivate(pTerm, (const TerminalDeleteMsg *) pMsg);
- break;
- case RUN_DIAGNOSTICS:
- status = Terminal_HandleRunDiagnostics(pTerm, (const RunDiagnosticsMsg *) pMsg);
- break;
- case PERFORM_SWITCHOVER:
- pOtherTerm = TerminalManager_FindTerminal(pMgr, pMsg->otherTerminalId);
- status = Terminal_HandleOutOfService(pTerm);
- status1 = Terminal_HandleInService(pOtherTerm);
- break;
- }
- }
- free(pMsg);
- }
Terminal
Terminal.h
- /* Terminal struct header file. */
- #include "Msg.h"
- #define UNKNOWN 0
- #define OUT_OF_SERVICE 1
- #define INSERVICE 2
- /* Terminal struct */
- typedef struct
- {
- /*...*/
- int terminalId;
- int terminalType;
- int terminalStatus;
- } Terminal;
- /*
- Prototypes for Terminal structure related functions. Helper
- functions needed by these functions are marked static are not
- included here.
- */
- void Terminal_Activate(Terminal *pTerm, const TerminalCreateMsg *pMsg);
- void Terminal_Deactivate(Terminal *pTerm, const TerminalDeleteMsg *pMsg);
- int Terminal_HandleRunDiagnostics(Terminal *pTerm, const RunDiagnosticsMsg *pMsg);
- int Terminal_HandleOutOfService(Terminal *pTerm);
- int Terminal_HandleInService(Terminal *pTerm);
- void Terminal_Construct(Terminal *pTerm);
- void Terminal_Destroy(Terminal *pTerm);
Terminal.c
- /* Terminal struct source file. */
- #include "Terminal.h"
- #include "Msg.h"
- #include <stdlib.h>
- /*
- Terminal_SendMessage is not visible to outside the Terminal.c file.
- This is equivalent to a private method in C++.
- */
- static void Terminal_SendMessage(Terminal *pTerm, Msg *pMsg)
- {
- /*...*/
- }
- void Terminal_Construct(Terminal *pTerm)
- {
- pTerm->terminalId = UNKNOWN;
- pTerm->terminalType = UNKNOWN;
- pTerm->terminalStatus = UNKNOWN;
- }
- void Terminal_Destroy(Terminal *pTerm)
- {
- /*...*/
- }
- int Terminal_HandleRunDiagnostics(Terminal *pTerm, const RunDiagnosticsMsg *pMsg)
- {
- int status = 1;
- /*...*/
- return status;
- }
- int Terminal_HandleOutOfService(Terminal *pTerm)
- {
- int status = 1;
- pTerm->terminalStatus = OUT_OF_SERVICE;
- /*...*/
- return status;
- }
- int Terminal_HandleInService(Terminal *pTerm)
- {
- int status = 1;
- pTerm->terminalStatus = INSERVICE;
- /*...*/
- return status;
- }
- void Terminal_Activate(Terminal *pTerm, const TerminalCreateMsg *pMsg)
- {
- TerminalCreateAck *pAck;
- pTerm->terminalId = pMsg->header.terminalId;
- pTerm->terminalType = pMsg->header.terminalType;
- pTerm->terminalStatus = pMsg->header.terminalStatus;
- /*...*/
- pAck = (TerminalCreateAck *)malloc(sizeof(TerminalCreateAck));
- pAck->header.terminalId = pTerm->terminalId;
- pAck->header.terminalStatus = pTerm->terminalStatus;
- Terminal_SendMessage(pTerm, (Msg *)pAck);
- }
- void Terminal_Deactivate(Terminal *pTerm, const TerminalDeleteMsg *pMsg)
- {
- /*...*/
- pTerm->terminalId = UNKNOWN;
- pTerm->terminalType = UNKNOWN;
- pTerm->terminalStatus = UNKNOWN;
- /*...*/
- }
Msg.h
- /* Messages used by the Terminal and TerminalManager classes. */
- #ifndef MSG_H
- #define MSG_H
- enum MsgType
- {
- CREATE_TERMINAL,
- DELETE_TERMINAL,
- RUN_DIAGNOSTICS,
- PERFORM_SWITCHOVER
- };
- typedef struct
- {
- /*...*/
- int msgType;
- int terminalType;
- int terminalId;
- int otherTerminalId;
- int terminalStatus;
- } Msg;
- /* Message used to create a terminal. */
- typedef struct
- {
- Msg header;
- }TerminalCreateMsg;
- /* Acknowledgement to Terminal Create message. */
- typedef struct
- {
- Msg header;
- } TerminalCreateAck;
- /* Terminal Delete message */
- typedef struct
- {
- Msg header;
- } TerminalDeleteMsg;
- typedef struct
- {
- Msg header;
- } RunDiagnosticsMsg;
- #endif
Explore More
- Compare C++ and the equivalent C code for class declarations and method invocation
- Compare C++ and the equivalent C code for inheritance and virtual functions.