28 Dec, 2010, RoFAdmin wrote in the 1st comment:
Votes: 0
Hey all-

Well in the process of working on my mud here i decided i wanted to make use of some of the functionality of c++

So before i go jumping in head first, i figured i would ask for any suggestions/pointers from those of you who have done this.

I know there is already versions of ROM converted over, but i have already taken the time to strip ROM down to its barebones (where i like it)
and begun adding stuff on-top and dont really cherish the idea of redoing this (it took FOREVER).

Ive looked around on the forums and ive found little bits of information here and there, but i was hoping someone might have a more in-depth knowledge to share.


Thanks in advance
28 Dec, 2010, RoFAdmin wrote in the 2nd comment:
Votes: 0
nvm, i decided to jump head in, and completed it myself. Thanks anyways for the help i know was sure to come :)
29 Dec, 2010, Runter wrote in the 3rd comment:
Votes: 0
For the benefit of future readers: C code is still (mostly) valid in C++. So converting a stripped down codebase to use C++ is as simple as changing gcc to g++ in your makefile. (Or whatever your compilers of choice are.) Converting to a object oriented design (which is often implied) is a slightly more difficult task. Just compiling for the benefit of some cpp features is pretty simple.
29 Dec, 2010, David Haley wrote in the 4th comment:
Votes: 0
Runter said:
So converting a stripped down codebase to use C++ is as simple as changing gcc to g++ in your makefile.

Putting on the Pedantic Hat 2010 (TM), it's not quite this simple: as Runter said, C code is only mostly valid in C++. You can no longer have variables named 'class', for example, and C++ tends to be stricter about things like const correctness. Depending on how much not-quite-right code you had that C tolerated, the process can be somewhat tedious as it would require a lot of repetitive and boring fixes.

That said I completely agree that
(1) converting to C++ compilation
and
(2) converting to C++ object-oriented design
are two completely different problems, the first being far easier than the second.
30 Dec, 2010, quixadhal wrote in the 5th comment:
Votes: 0
If you are starting from stock ROM without any additions, take a look at the RaM project, somewhere in the repository. It was left somewhere around the point of having everything in C++ and just starting to convert to iterators and std::string. Still not an OO design by any stretch, but it might save you a little legwork.
30 Dec, 2010, Runter wrote in the 6th comment:
Votes: 0
Quote
Putting on the Pedantic Hat 2010 (TM), it's not quite this simple: as Runter said, C code is only mostly valid in C++.


Well, yes. I suppose what I meant was the more stripped down it is the less work (and possibly none) the conversion will be. Small programs more or less convert directly. Modern gcc compiled applicatons convert pretty smoothly except for reserved words. So yeah, I agree. I'll even go one step further and say there's little reason for a mud to be compiled with gcc at all even if relatively no cpp features are used. It's worth cpp even if you're only using the standard template library in my opinion.
31 Dec, 2010, RoFAdmin wrote in the 7th comment:
Votes: 0
Alright, so i figured i should come back and write all the things i can remember having to do to get this to compile cleanly.

1) in various place in the codes variables are cast from void to a different data type simpAlright, so i figured i should come back and write all the things i can remember having to do to get this to compile cleanly.

1) in various place in the codes variables are cast from void to a different data type simp[ly using the = command. What you have to do is go through all these
spots and cast it to the various data types
EXAMPLE:
in recycle.c in new_obj you have
[code]OBJECT_DATA *obj;[/code]
and later
[code]obj = alloc_perm(sizeof(*obj));[/code]
change the second line to this
[code]obj = (OBJ_DATA *) alloc_perm(sizeof(*obj));[/code]

And you do just that for all the places it complains about such things

2) All global variables need to be moved out of merc.h and put them in a .c file somewhere, i suggest comm.c
Then add in extern's for all of them i merc.h so they are thus accessible as before.

3) you'll get alot of complaints about comparison between signed and unsigned integer.
what i found all these to be, at least in my strip down base, was that in all the places it was complaining a variable of type int was being compared to a function call such as strlen or something similar. So whats the problem. Well more then likely thew case is that the function call isnt returning an integer, instead its returning a variable or type size_t, so to fix this change your variable declaration from an integer to size_t.

4) in merc.h there is a #define for bool, remove this

5) You gonna get some errors about comparing const char* and char* variables, or maybe it was casting them or something i dont remeber. Either way the answer is simply dont do this. Most cases that i saw in the code the define something as const char it really wasn't needed to be a const char.

I think there was a few other minor things, though i dont remeber off hand. To be honest goggling the errors i didnt understand was most useful and usually the answer i needed was on the first page.


Hope this helps other people, if you got any questions just ask me.
31 Dec, 2010, Tyche wrote in the 8th comment:
Votes: 0
RoFAdmin said:
2) All global variables need to be moved out of merc.h and put them in a .c file somewhere, i suggest comm.c
Then add in extern's for all of them i merc.h so they are thus accessible as before.


There aren't any global variables defined in merc.h
If there were it wouldn't compile under regular C…that is you'd get linker warnings.
You might want to recheck this.
31 Dec, 2010, quixadhal wrote in the 9th comment:
Votes: 0
RoFAdmin said:
5) You gonna get some errors about comparing const char* and char* variables, or maybe it was casting them or something i dont remeber. Either way the answer is simply dont do this. Most cases that i saw in the code the define something as const char it really wasn't needed to be a const char.


Actually, I'll dispute that advice. Declaring something as a const char * is a hint to the compiler that the contents of said pointer will not be changed by anything inside the function accepting that parameter. This isn't worthless, it allows the compiler to flag things which would cause such changes to happen, thus allowing you to fix them.

A great many memory corruption (string corruption) errors in old DikuMUD code stem from code mistakenly writing to strings that weren't really copies. Rom had it's own shared string system that makes bad code more likely to cause damage when that kind of thing happens, since now it'll corrupt the templates as well as the individual objects.

Now, it *IS* a lot of tedius work to properly fix all those warnings/errors. I know, I went through and did that for RaM, as well as my own codebase. :)
31 Dec, 2010, RoFAdmin wrote in the 10th comment:
Votes: 0
Tyche:

There were defiantly global variables defined in my merc.h file at the end. It was all the list for characters, room, objects, stuff like char_list and top_affect etc.
Perhaps it got moved here previously at some point (ive been tinkering with this base on and off for years). But it did compile cleanly and never got any linker warnings. So my advice here may be a tad faulty since i haven't looked at a stock rom base in awhile, tyche is more then likely right by default there are no global variables here. In the event you put some in there, or moved some in there though you will need to do this.

quixadhal:

Good point, im only giving advice from my strip down base, and pretty much all the places it was attempting to use a const char, it was simply unneeded. For those of you with a more complete ROM base it is entirely likely there are places you may need to fix this another way. I want to say in total i only had 4 errors like this, if that gives you an idea of how stripped down and altered my base is compared to standard rom ;)
01 Jan, 2011, Davion wrote in the 11th comment:
Votes: 0
Not sure if you're going to run into this but this may help others.

In db.c there's a couple gotcha's. I'll just pull one of the examples but I believe this particular instance happens twice. C++ has issues with lack of casting, different types, and also, casting on the left side of the operation.

So this:
pMem += sizeof(*magic);


Needs to be switched too:
pMem = (void *) ((long) pMem + (long) (sizeof(*magic)));


There might be a nicer way to do this, but this is how I did it ;).
01 Jan, 2011, David Haley wrote in the 12th comment:
Votes: 0
That's a very dangerous way of doing things: you should never cast pointers to a numeric type and then back to a pointer again. It's a great way to introduce incompatibilities with 32 vs. 64 bit code. I'm fairly surprised that the compiler was not happy with straightforward pointer arithmetic; I'd have to see the full case to have a better idea of what was happening.
01 Jan, 2011, Runter wrote in the 13th comment:
Votes: 0
Shouldn't the size of pointers always be the same size as long, though?
01 Jan, 2011, David Haley wrote in the 14th comment:
Votes: 0
A 'long' is defined to be an integer at least as large as 'int'. By definition it is not guaranteed to be of the same size as a pointer. But, in practice, it usually is. Still, you should never need to cast pointers to numbers to do pointer arithmetic on them – that's an indication that something else bizarre is happening.
01 Jan, 2011, RoFAdmin wrote in the 15th comment:
Votes: 0
I actually did come across that problem and i forgot about it when i wrote this up. The work around i used is actually in my -pendantic -ansi thread.

The solution was provided by kaz, and seem to be working well.
pMem = (char*)pMem + sizeof(*magic);
0.0/15