Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Using multiple C++ libraries in a project 1

Status
Not open for further replies.

globos

Programmer
Nov 8, 2000
260
0
0
FR
Hi,

I am working on a project that use two C++ libraries : Qt and Open Cascade. Concerning this project we have defined our naming norms for classes, features, etc.
The first problem is that those norms are different from those of Qt and Open Cascade, and naming norms are different between Qt and Open Cascade.

Naming norms for Qt are very like Java style, example :
QWidget::setWidth (int width)

Those of Open Cascade, example :
AIS_InteractiveObject::SetWidth (int width)
Where the class prefix "AIS" is the name of the owner package

Our norm is based on Eiffel, example :
MATERIAL::set_name (STRING name)


This means that the software text of our project is written using three different norms!

What I want to know is : is there a tool that can process C++ files and translate them according to a given norm? This tool might be based on names mapping informations, or stuff like that, but I couldn't find such a tool.
I think this kind of problem is pretty recurrent in C++ projects.

--
Globos
 
What is this AIS_InteractiveObject...is it a object?
Actually i used staic(LIB) as well as dynamic libraries(dll)..
Unfortunately I too don't have any idea about any such tool which can keep the norms of dll same
 
AIS_InteractiveObject is a class.
As well as QWidget, MATERIAL and STRING in the examples i gave.


--
Globos
 
Dont know how the warious norms are defined, but perhaps you could fix it with Find/Replace using regular expressions. awk is a great tool for for things like this if the F/R function in Visual Studio isn't enough.

Could you specify what is special of each norm?



/Per
[sub]
if (typos) cout << &quot;My fingers are faster than my brain. Sorry for the typos.&quot;;
[/sub]
 
If you want to link in the libraries, you are stuck with the class and method names as defined in the header files that were delivered with the libraries. However, if you want to have your code look like it was ALL developed in the same shop, two possible solutions come to mind.

1) Create macros that map your home-grown naming conventions onto the existing class and method names. For example, if your shop conventions specify that class names should start with C (for Class), but the XYZ library begins all of their class names with XYZ, you could write something like this:

#define CClassOne XYZClassOne

2) Derive classes from the classes supplied by the library. You would name your new classes according to your conventions. You would also need to create new methods, supplying names that conform to your shop's conventions, that invoke the methods supplied by the library. For example, if your conventinos prescribe that method names be of the format VerbNoun, but the library supplies methods in the format verb_noun, you might write:

class CClassTwo : public XYZClassTwo
{
public:
CClassTwo(void) : XYZClassTwo() {}

int ActionObject(void) { action_object(); }
};

Both of these will be quite a bit of work if there are a lot of classes with a lot of methods. I have not considered what happens if the library supplies templates as well as classes, but you should.

One of the benefits of either of these methods is that the &quot;conversion&quot; code can exist only in a header file.

Theoretically, if you knew the layout of the library file, you could write a program that could replace the names of the classes and methods, but that program would have to be smart enough to perform the name mangling required for overloading method names.

Perhaps the best option is to leave the names in the libraries as they were delivered to you. Each time you use a class or call one of its methods, you will be reminded that you are using an outside vendor's package. The resulting code will not have that homogeneous look that you prefer, but it will be obvious to the maintainers of the code where each piece of code came from.

OffByOne (Richard F. Johnson)

One year, two weeks, three days, 14 hours, 15 minutes and 38 seconds. 6886 cigarettes not smoked, saving $1,119.09. Life saved: 3 weeks, 2 days, 21 hours, 50 minutes.
 
Thank you Perfnurt and OffByOne.

I already tried the first solution you gave, i.e. use macros to do the mapping. Unfortunately, it ran into problems that made me leave this solution.
As I have to map classes and features names, ambiguity problems occur with this solution, suppose you have the following mapping :

#define INTERACTIVE_OBJECT AIS_InteractiveObject
# define set_width(a) SetWidth(a)
#define QWIDGET QWidget
# define set_width(a) setWidth(a)

then it leads to a problem if :
QWIDGET* awidget;
INTERACTIVE_OBJECT io;
awidget->set_width(...);
io->set_width(...);//which version to choose?

One solution is to prefix macros, like qt_set_width, or occ_set_width, but it is really a pity. And the problem occurs with overloaded features of a class too.

I did not try the second solution, because i'm afraid that the amount of work is too huge, and there might also be other severe problems that can happen, like memory management.

Those last days, I began to write a tool that analyses C++ files and translate them into either our norm or the effective norms.
It is based on a mapping file, like this :
class:QWIDGET=QWidget
set_width=setWidth
class:INTERACTIVE_OBJECT=AIS_InteractiveObject
set_width=SetWidth
...

The tool must analyse also the variables(and their types) used in a C++ file, in order to solve ambiguity problems.
This tool works fine on simple programs like the one I gave to show macros problems.

But it needs to move to a C++ parser to handle all the cases, particularly twisted cases like :

for (list<INTERACTIVE_OBJECT>::iterator i = ...)
{
(*i).set_width (5);//must replace set_width by SetWidth
}

The main drawback of this solution is that you have two versions of the software text, one that is homogeneous, but not directly compilable, and one inferred from the previous that is compilable. Fortunately, it is really possible to have a bijection between the two forms, so it simplifies their management.



--
Globos
 
What is the problem really? Do you get name collisions? If so, put them in separate namespaces (and dont use any sneaky &quot;using namsespace whatever;&quot;.

To you get bugs due to the naming convention? If not, perhaps reconsider if its worth the effort.

Besides, there might be a point in different norms if they infact reflect different libraries.
For example, I only follow the MFC norm (prepend with C, SetName, m_Member etc) , if its an MFC specific class (otherwise no prepend, setName, mMember). In other words the naming convention can tell you something about the code.

I would avoid macros, its is most likely to obfuscate rather than clarify the code.

>must replace set_width by SetWidth
Well...if you MUST, what about a simple Find/Recplace on all files of set_width (whole word, type sensitive) => SetWidth

/Per
[sub]
if (typos) cout << &quot;My fingers are faster than my brain. Sorry for the typos.&quot;;
[/sub]
 
>>Well...if you MUST, what about a simple Find/Recplace on all files of set_width (whole word, type sensitive) => SetWidth

I explained this cannot work properly, as different classes have features that have the same translation. Reconsider the code example :

QWIDGET* awidget;
INTERACTIVE_OBJECT io;
awidget->set_width(...);
io->set_width(...);

If I do a F/R(set_width -> SetWidth), I get :
awidget->SetWidth(...);
io->SetWidth(...);

And the real feature name of 'set_width' for QWIDGET is not 'SetWidth' but 'setWidth'.
So F/R does not work in all cases.


--
Globos
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top