C2C++(TM) Paper Copyright(c) 1993. All rights reserved worldwide. December 1993 _________________________________________________________________ 1. Introduction This paper describes an automated suite of tools named C2C++(TM) which provides the conversion of C code into object oriented C++ code. I will attempt to make this paper short and punchy rather than long- winded since time is money. This paper is targeted to those who have an existing investment in C and would like to embrace object orientation through the latest ANSI draft C++ language. It is expected that you are familiar with object oriented terminology since you would have done some up-front investigation as to what you should do with your existing investment in C code. I believe it is widely accepted amongst the programming fraternity that object orientation offers enormous productivity gains in both large and small projects, for the creation and maintenance of code and believe me, no matter what the critics say, it does. For those who would like to become more familiar with object oriented terminology and methodology, and those who have yet to accept object orientation, I recommend reading in the following order some of the most thought provoking titles available on the subject specifically for C programmers: "C++ Inside and Out " by Bruce Eckel. (This is for those who want to get up to speed quickly) "Effective C++" by Scott Meyers, (This is for those who want to find out why their code does not work) "The Annotated C++ Reference Manual" (also known as the ARM) by Bjarne Stroustrup and Margaret Ellis, (This for those who think they know it all) "Advanced C++" by James Coplien (This is for those who realize "we aren't worthy" see the movie "Waynes World", then you'll understand) _________________________________________________________________ 2. Protecting Your Existing Investment in C code With this new wave of technology, comes many questions and challenges. One with the most economic and technical impact, is what to do with your existing investment in C code, since this will directly affect your bottom line? It is simply not viable to throw out your existing C code which has been debugged and proven reliable over its development life cycle. There are many "challenges" (this is the word people use when it is extremely difficult) which prove painful and time consuming in interfacing C code to C++ code if you really want to take advantage of the object oriented paradigm (which is obviously why C++ was created). Having experienced the "challenges" and pain on the conversion of a number of commercial projects, the smallest of which has been no less than 400, 000 lines of code, with more than 1000 modules in more than 100 sub directories, I have developed a strong foundation of a suite of programs called C2C++(TM). I have decided to market C2C++(TM) which will provide your organization with the same competitive advantage that many other commercial publishers now have through the leveraging of their existing investment in C code. Simply put, if you want to convert your C code to C++ code, I believe, having gone through the exercise a number of times, that C2C++(TM) is the least painful and most economical way to do it. _________________________________________________________________ 3 C2C++(TM) conversion will: 1. Preservation and enhance your existing investment in C code. This has already been discussed above. 2. Automate the migration of your procedural C world to the object oriented C++ world. Manual migration is error prone and not economical. 3. Separate the interface description from the implementation of classes This is a classic benefit of object orientation which is achieved through organization and structuring with C++. 4. Simplify maintenance For example: declarations are no longer scattered throughout your code. 5. Make extensions easier You can code entirely with C++ without having to worry about burdensome interfaces between C code and C++ code, making further extension simpler and easier. 6. Provide a rapid development process of C++ classes to establish a working base from code that you are already familiar with. There cannot be any quicker way for your organization to exploit this new technology with minimized risk. 7. Enable your programmers through a faster learning curve by observing their existing code, which they are familiar with, transformed into well organized object oriented C++ code. There is minimal time lag between deciding upon exploiting object orientation and experiencing its benefits, without abandoning your existing code. _________________________________________________________________ 4. Technical consideration of the C2C++(TM) conversion: 1. C2C++(TM) considers your program from a global perspective,not just one module or one directory of modules in isolation. This is achieved through a multi-pass program analyzer that creates its own database to describe your code. 2. Converts existing C code (data and functions) into object oriented C++ code and objects. C2C++(TM) makes full use of classes, structures and organizes your code through the process. 3. Automatic conversion of structs into classes. Fast, painless and error-free. 4. Automatic detection of member functions and static functions of classes. Structures your functions by collecting them into groups which manipulate the same type of data making your code more understandable and therefore simpler to maintain. 5. Automatically classifies functions into private,protected or public given simple rules. This will allow you to take advantage of the facilities that class inheritance provides. 6. Automatically formats your class declarations and header files into a standard layout. This provides an orthodox canonical format (a better structure from within which to work) and therefore makes your code more readable for better maintenance and bug finding. 7. Automatically produces nested classes. This will reduce global name space crowding. ( You can achieve this manually, but you might work up a sweat) 8. Automatically detects normal and static data members of classes. This is simply good C++ programming practice because it collects related information together. 10. Automatically generates new translated header and source code files. This is why you are doing the conversion in the first place. _________________________________________________________________ 5. A simple example of the C2C++(TM) conversion for the uninitiated Some of the features shown in this example includes: 1. Classification of a function into its class. 2. Simplification of a function name through renaming. 3. Removal of the first parameter of a class member function. 4. Translation of references to the member object within expressions within a member function. 5. Translation of member function call expressions. Comments that I have inserted afterwards for better reading regarding the conversion process are inserted into the example code and are recognizable by their prefix of: // ** _________________________________________________________________ 6. Original C source code: BOOL IsControlVisible(Form* pForm, int idControl) { Control* pControl; if (idControl < 0 || idControl > pForm->cControls) return FALSE; pControl = pForm->pControls[idControl]; return ControlIsVisible(pControl); } _________________________________________________________________ 7. Converted C++ source code: // ** The function was classified to be a member of the Form class. // ** Its first parameter was removed because it is now implied. BOOL Form::IsControlVisible(int idControl) { Control* pControl; // ** Member object reference pForm removed. if (idControl < 0 || idControl > cControls) return FALSE; // ** Member object reference pForm removed. pControl = pControls[idControl]; // ** The expression was translated to put its first parameter in front // ** of the function call brackets. // ** The function call uses the new function name. return pControl->IsVisible(); } _________________________________________________________________ 8. A more complex example of C2C++(TM) conversion Some of the features shown in this example includes: 1. Classification of a function into its class. 2. Simplification of a function name through renaming. 3. Removal of the first parameter of a class member function. 4. Translation of references to the member object within expressions within a member function. 5. Translation of member function call expressions. 6. Creation of a nested class. 7. Classification of generic POBJECT pointers into pointers to specific classes. 8. Usage of C++ templates to handle reference counted class pointers. 9. One method of detection of static data members of a class. 10. Classification of a function as being a static member of a class. 11. Standardized layout of header files. 12. Automatic header file inclusion of reference classes within a class declaration. 13. Creation of default assignment and copy constructors. 14. Automatic protection against including a header file multiple times. 15. Consolidation of multiple related header files. _________________________________________________________________ 9. Original C header file 'Pane.h': typedef struct { HWND hwnd; // window handle (client if in MDI frame) } VIEWPANE, *PVIEWPANE; _________________________________________________________________ 10. Original C header file 'Control.h': typedef struct { // Window interface related information. FLAG fHidden; // whether Control should be allowed to be visible USHORT cViews; // number of views of this object PVIEWPANE pViews; // definition of each view // Relationships. POBJECT pParent; // parent control (for nesting within dialogs) POBJECT pForm; // Form containing the Control USHORT cSub; // number of related subordinate Controls PPOBJECT ppSub; // related Controls subordinate to this one // Actions in response to standard events. POBJECT apAction[EVENT_LAST]; } CONTROL, *PCONTROL; typedef struct { // status variables for controlling mouse dragging USHORT usButton; // button 1 or 2 or none or both. FLAG fAlt; // whether Alt pressed when drag started FLAG fControl; // whether Control pressed when drag started FLAG fShift; // whether Shift pressed when drag started } CONTROL_STATIC; _________________________________________________________________ 11. Original C source code file 'Control.c': // -------------------------------------------------------------------------- HWND ViewPaneQueryHWND(PVIEWPANE pViewPane) { return pViewPane->hwnd; } // -------------------------------------------------------------------------- // Finalise all updating of views of the Control. FLAG ControlViewsUpdate(PCONTROL pControl) { USHORT i; for (i=0; icViews; i++) { WinUpdateWindow(ViewPaneQueryHWND(&pControl->pViews[i])); } return TRUE; } // -------------------------------------------------------------------------- PVOID ControlWait(FLAG fWait, PVOID hptrOld) { if (fWait) { hptrOld = (PVOID) WinQueryPointer(HWND_DESKTOP); WinSetPointer(HWND_DESKTOP, WinQuerySysPointer(HWND_DESKTOP, SPTR_WAIT, FALSE)); } else { WinSetPointer(HWND_DESKTOP, (HPOINTER) hptrOld); } return hptrOld; } _________________________________________________________________ 12. Generated C++ header file 'Control.hpp': // ** Automatic protection against including a header file multiple times #ifndef _CONTROL_ #define _CONTROL_ // ------------------------------------------------------------------------- // INCLUDE FILE DEPENDENCIES: // ** Automatically includes headers for common and reference classes. #ifndef _Common_ #include "Common.hpp" #endif #ifndef _Handle_ #include "Handle.h" #endif #ifndef _Object_ #include "Object.hpp" #endif // ------------------------------------------------------------------------- // FORWARD DECLARATIONS OF ALL NON-NESTED CLASSES DEFINED WITHIN THIS MODULE: // ** Predeclares all classes declared in this module to allow cross-references from one class to another // ** Uses a typedef to simplify access to a template class used for managing Control pointers. class Control; typedef Control* PCONTROL; typedef ObjectHandle < Control > HandleControl; // ======================================================================= // ** You can define rules on the database which establish the parent class of a class class EXPORT Control : public SharedObject { // ** Automatically creates nested classes where appropriate // ** and insert then into the enclosing class // ---------------------------------------------------------------------- // NESTED CLASSES: // -------------------------------------------------------------------- class EXPORT ViewPane : public Object { // ** Automatically labels each section of the class declaration for better // ** readability and maintainability. // ---------------------------------------------------------------------- // DATA MEMBERS: public: HWND hwnd; // window handle (client if in MDI frame) // ---------------------------------------------------------------------- // FUNCTION MEMBERS: private: // ** Automatically inserts these declarations so that your C++ compiler // ** won't surprise you // ** by quietly creating its own code for them. // ** It also serves as a reminder for you top implement these functions // Declared private and not defined in order to trap unwanted usage. ViewPane(const ViewPane& rItem); ViewPane operator= (const ViewPane& rItem); public: HWND QueryHWND(); }; typedef Control::ViewPane VIEWPANE; typedef Control::ViewPane* PVIEWPANE; // ** The banner and indentation tells us we are back to the main class' definition of Control. // ---------------------------------------------------------------------- // DATA MEMBERS: public: // Window interface related information. FLAG fHidden; // whether Control should be allowed to be visible USHORT cViews; // number of views of this object PVIEWPANE pViews; // definition of each view // ** This section shows a special feature of C2C++(TM) which allows for improved // ** conversion of quasi object oriented C code. // ** In this case the old C code uses a generic "POBJECT" which is a pointer // ** to a member of an unknown class, but // ** C2C++(TM) was able to transform this pointer into a managed pointer // ** (a handle) to the correct class of object, as determined // ** by the application of rules defined to C2C++(TM). // Relationships. HandleControl pParent; // parent control (for nesting within dialogs) HandleForm pForm; // Form containing the Control USHORT cSub; // number of related subordinate Controls HandleControl* ppSub; // related Controls subordinate to this one // Actions in response to standard events. HandleAction apAction[EVENT_LAST]; // ---------------------------------------------------------------------- // FUNCTION MEMBERS: private: // ** Automatically inserts these declarations so that your C++ compiler // ** won't surprise you by quietly creating its own code for them. // ** It also serves as a reminder for you top implement these functions // Declared private and not defined in order to trap unwanted usage. Control(const Control& rItem); Control operator= (const Control& rItem); public: FLAG ViewsUpdate(); // ** Notice how the class declaration is ordered according to // ** standard layout which allows for quick finding of declarations and // ** easy detection of missing functions. // ---------------------------------------------------------------------- // STATIC DATA MEMBERS: private: // ** These variables were known to be static because of the naming convention of the struct. // status variables for controlling mouse dragging static USHORT usButton; // button 1 or 2 or none or both. static FLAG fAlt; // whether Alt pressed when drag started static FLAG fControl; // whether Control pressed when drag started static FLAG fShift; // whether Shift pressed when drag started // ---------------------------------------------------------------------- // STATIC FUNCTION MEMBERS: static PVOID Wait(FLAG fWait, PVOID hptrOld); }; #endif _________________________________________________________________ 13. Converted C++ source code file 'Control.cpp': // -------------------------------------------------------------------------- // ** The function was classified into the nested Control::ViewPane class. // ** The first parameter was removed because it is now implied. HWND Control::ViewPane::QueryHWND() { // ** The expression was simplified because this is a member function. return hwnd; } // -------------------------------------------------------------------------- // Finalise all updating of views of the Control. FLAG Control::ViewsUpdate() { USHORT i; // ** Superfluous references to the member function object are removed // ** from all expressions. for (i=0; i