Skip to main content
GameDev.net gamedev.net
🔒 Locked

Object Oriented C

Started by grabiller Oct 30, 2006 at 6:42 AM 18 replies 3k views
Original Post
grabiller
grabiller
Hi, just out of curiosity, does anyone knows if there are current commercial games and/or game engines using any form of Object Oriented C ( in the general sense, not specifically C++ "simulation" in C, but in wich the concept of class exist ) rather than C++, and this, on purpose ? If so, I would be interrested to know their reasons, if they are known. Thanks in advance for any information.
guy rabiller | President, CEO & CTO | m3factory
Almonsin
Almonsin
Hi
I don't really understand what you need, but I think you should have a look at Objective C.
jpetrie
jpetrie
Well, a large percentage of the games you'll see out there are probably written more in "C with classes" (which is C++ but using a lot of C paradigms) than they are "C++," if that is what you're getting at.

As for specifically emulating the native features related to OO in C++ in a language without them, like C... I don't know that this is ever done in practice on a large scale (e.g., the entire project). There is, generally, no reason to do so -- it offers no advantages and creates a lot of additional work. You should just use the language appropriate for the task.

Sometimes people will emulate certain subsets of C++ -- such as RTTI -- rather than use the native implementation, but this is still using C++, generally. And it's usually done for misguided reasons.

But perhaps I've misunderstood, are you talking about Objective-C instead, or some other language that looks like C but doesn't have native support for features that make implementing object orientated design easier?

Ryan_001
Ryan_001
Quote:
Original post by jpetrie
As for specifically emulating the native features related to OO in C++ in a language without them, like C... I don't know that this is ever done in practice on a large scale (e.g., the entire project). There is, generally, no reason to do so -- it offers no advantages and creates a lot of additional work. You should just use the language appropriate for the task.


Likewise I'm unsure of what ur asking. But as far as emulating OO in C, I know Mame uses a simple inheritance scheme for their hardware 'classes', all programmed in C. If you're masochistic u can peruse the source code here: www.mame.net

glaskows
glaskows
Yeah, lots of games have done this.
Look for example at Homeworld 1 code... if a game is written in C is probably that they made some kind of object oriented thingies on top. I mean, it's pretty common to use function pointers inside structs, and that's some kind of emulating a method of C++.
grekster
grekster
I think the Quake engines were supposed to be quite OO
Quote: Original post by BosskIn Soviet Russia, you STFU WITH THOSE LAME JOKES!
grabiller
grabiller

Sorry for beeing unclear.

Let me re-phrase my question, by splitting it in two:

1) Are there any current known commercial games and/or game engines written in C instead of C++ ?

2) Among those written in C, are there some written with an OO approach, by using concepts such as classes, encapsulation, inheritance ( interfaces ), rtti, even reference counting ( albeit not specific to OO ), etc.. ( emulated with structures, opaque pointers, etc.. ) ?

By Object Oriented C I mean having object oriented concepts and algorithms rather than pure procedural ones. I don't mean full OO C wich try to emulate all features of C++.

guy rabiller | President, CEO & CTO | m3factory
jpetrie
jpetrie
Quote:

Likewise I'm unsure of what ur asking. But as far as emulating OO in C, I know Mame uses a simple inheritance scheme for their hardware 'classes', all programmed in C. If you're masochistic u can peruse the source code here: www.mame.net

Was that directed at me (you quoted me)? I'm not asking anything.

I was unable to find browsable source code from the page you linked to (there might be downloadable source code, but I'm not that interested).

I'm referring to, for example, emulating the concept of a "member function" in C, which disallows them natively. Or implementing dynamic dispatch (which means you'll be manually setting up, typically, some kind of virtual table and a bunch of glue code to dispatch via it). Usually this requires adherance to coding standards that cannot be guaranteed by the compiler (any function that is supposed to be a "class method" would need, for example, the first argument to be a pointer to the class so that the glue macro typically used to make invoking "methods" easier would function correctly). Attempting to emulate the paradigms and idioms of one language in another language that lacks native support for said paradigms and idioms generally makes code next to unmaintainable and a disgusting mess. Your comments with respect to being "masochistic" to want to view the MAME source suggests that this is true.

It's ugly, and what advantage does it really offer them (or anybody in general)? Certainly not clarity. Speed? Not likely, since you're unlikely to achieve the same speed that languages with native support can attain without reimplementing what those languages do under the hood, which takes a lot of time and effort that could be better spent elsewhere... and still only gets you just as fast, not faster. If you're really, really good maybe you can achieve a faster implementation, but you're likely to have to make some sacrifices and the overall performance boost is unlikely to be worth the effort you put into it.

EDIT:
It seems the OP was, in fact, more interesting in the use of concepts rather than specific language features. This is slightly more common, although the number of games written in pure C now (versus "C with classes" and "real" C++) is smaller. It likely surviving mainly in the embedded markets (small consoles, cell phones, devices like that). I don't know enough about said markets to offer much specific insight.
Ryan_001
Ryan_001
Quote:
Original post by jpetrie
Was that directed at me (you quoted me)? I'm not asking anything.


Sorry, I wasn't trying to say you were wrong. In fact I agree with what u said. And the quote was more of a, 'ya, like this guy said', statement aimed at the OP. The source code is downloadable, and there's alot of it to sift through if u are interested.

Both to you and the OP, the link I refered to is a good example of how simple OO can be implemented in C. Mame is an arcade emulator and emulates a ton of different types of old hardware. The author(s) have different structs representing parts of the old arcade boards (CPU's, sound, graphics, input, ect...) which use function pointers much like virtual functions. Then with some macro fun then implement inheritance, and a few other basic OO features. At first it seems rather chaotic, but it is rather ingenious (or at least seemed to me) some of the tricks they use.

Anyways, its not like I would say its a good way to go, but it has been done. I imagine most engines and/or software written in this way would be rather old stuff that was designed before C++ was around, or perhaps (as in Mame's case) there wasn't a lot of good C++ compilers available and in order to keep things portable stuck with plain old C.

Aldacron
Aldacron
Quote:
Original post by grabiller1) Are there any current known commercial games and/or game engines written in C instead of C++ ?


C was used to create the server for Dark Age of Camelot. I've heard it was used in the renderer for Doom 3 (though the game itself is C++). The only way to know which current games are using C is to ask people who worked on them, unless the companies announced it somewhere.

If you step out of the realm of games and look at game tools, SDL is an example of an object oriented C library, as is Lua.

Quote:
2) Among those written in C, are there some written with an OO approach, by using concepts such as classes, encapsulation, inheritance ( interfaces ), rtti, even reference counting ( albeit not specific to OO ), etc.. ( emulated with structures, opaque pointers, etc.. ) ?


RTTI and reference counting have nothing to do with object oriented programming. Neither do classes. 'Class', a keyword found in most languages with built-in OO support, means a 'class of objects'. Objects are the heart of OO, not classes. Encapsulation, as the term is commonly used (i.e. to mean data-hiding), isn't even necessary to have an OO design, though encapsulation as containment (i.e. each object contains its own properties) is. Also, free standing functions that manipulate objects are no less OO than class methods, so the idea that OO in C means 'structs with pointers' is way off.

Over the years, the concept of object orientation has been made more complex than it really is. At its most basic, OO design is the process of breaking a problem into component objects that contain their own properties. Classes, member visibility (private, public, protected), class methods... these are all language implementation details. Data-hiding is a technique used to improve the robustness and integrity of an OO design, not an OO feature itself.

People often throw about the phrase 'good OO' in reference to concepts that have nothing whatsoever to do with object orientation. If a design uses objects that have their own properties, that's good OO. Encapsulation, loose coupling, and other such concepts aren't 'good OO', but robust (flexible, extensible, maintainable) design.

Quote:
By Object Oriented C I mean having object oriented concepts and algorithms rather than pure procedural ones. I don't mean full OO C wich try to emulate all features of C++.


Many modern C programmers use a modular approach, with each source file representing a module and manipulating a particular class of objects:

// myobject.htypedef struct MyObject_s{   int x;   int y;} MyObject;extern MyObject* MyObject_Create(int x, int y);extern void MyObject_Destroy(MyObject* obj);extern void MyObject_DoSomethingWithTwoObjects(MyObject* obj, MyObject* two);  


The above example has no data hiding and there are no function pointers in the struct, but it is still object oriented. MyObject represents a class of objects, each instance has its own properties (x and y), and the functions are designed to manipulate instances of MyObject.

If you really wanted to hide the data, though, it's real easy:

// myobject.h// forward referencetypedef struct MyObject_s MyObject;extern MyObject* MyObject_Create(int x, int y);extern void MyObject_Destroy(MyObject* obj);extern void MyObject_DoSomethingWithTwoObjects(MyObject* obj, MyObject* two);extern void MyObject_GetXY(MyObject *obj, int *x, int *y); /************************************************/// myobject.cstruct MyObject_s{   int x;   int y;};...


Now x and y are essentially 'private' members. The drawback is that you lose the ability to declare instances of MyObject on the stack. Every MyObject must be allocated on the heap via MyObject_Create.

In C, emulating features that are found in most languages with built-on OO support, such as data-hiding and inheritance, is usually a trade off. You can get true data-hiding by restricting your objects to the heap; inheritance can be simulated in C in simple and complex ways, but both add a corresponding level of complexity to maintenance. On the other hand, data-hiding brings a level of safety and robustness to a design that isn't available if the object definition is entirely in the header, and simulated inheritance can make a library easier to use.

C was not originally designed with the OO paradigm in mind. But, it's still possible to have clean, object oriented interfaces that make C programs more maintainable than they otherwise would be. Ultimately, though, it generally requires more discipline on the part of the programmer than would be required when using C++ or Java.

As to why someone would do that, I think it mostly boils down to personal preference these days in the gaming world. I doubt there are many, if any, mainstream studios using C any more. The productivity gains of moving to C++ are just too much to pass up. Indie shops (not just the small guys, but also the big indies like id) can choose to use what they want. I would choose C over C++ any day of the week for my own projects (and have), simply because I've been using C for a long time now and I'm free to work at my own pace.

While you still will find people using C, I doubt you'll find people using the same design ideas C programmers employed 25 years ago. Modular design has been in use for quite a while and has evolved over the last 15 or 20 years to be more robust. There's a book by one of the developers of the lcc compiler called C Interfaces and Implementations. It was published in 1997, but the concepts it covers are still relevant. The book deals with how to implement reusable library designs in C by separating interface from implementation, a concept users of C++ and Java take for granted but C programmers were slow to adopt on a large scale. Anyone interested in C programming should read it.
grabiller
grabiller

Thanks everyone for your answers.

I think there are still some misunderstanding with my question - sorry again to not be as clear as I should - as I'm not asking "how to implement Object Oriented C".

My question is more some kind of "survey" on the current practices, and if there are still companies creating games and/or game engines in C rather than in C++ and why, and if so, if they use an Object Oriented approach or a "classic" procedural approach.

I agree with Zahlman ( "Nobody really agrees on what this "OO" thingy means../.." ) and Aldacron ( "../..Objects are the heart of OO, not classes../.." ), however I don't want to play smart here and play on the words or on semantics.

I think you got the point by what I mean with an Object Oriented approach in C.

If not, then lets say that the definition of Object Oriented C included in my question goes from a modular approach ( as Aldacron explained it ) up to complicated C++ "emulation" ( see: http://ldeniau.home.cern.ch/ldeniau/html/oopc/oopc.html for instance ).

I'm seeking for reasons why this would be done, rather than using C++.

I'm quoting Laurent Deniau from the previous url:

"../..These techniques may be useful for programmers who have not a C++ compiler for their architecture (calculators, small systems, embedded systems). It may also be useful for people who are disappointed by C++ compilers which do not behave like the norm says or even do not support all the C++ features or by C++ APIs that change from time to time. In fact, I don't know (at the revised date of this paper) any compiler which fully support the norm C++98. It is clear that the techniques presented here have not the pretension to replace C++, that is impossible without a cfront translator (OOPC uses only C macros and few C lines), but it provides enough to do serious OOP../.."

Perhaps other reasons are known ? Or may be specific case or experience where using an oriented approach even in C would have been more efficient than in C++.

Things like that.

Quote:
Original post by jpetrie
Well, a large percentage of the games you'll see out there are probably written more in "C with classes" (which is C++ but using a lot of C paradigms) than they are "C++," if that is what you're getting at../..


That's what I think too, and this will help clarifying my question as I'm talking about the exact opposite, writting in C but with a strong OO approach in mind.

Quote:
Original post by Ryan_001
Likewise I'm unsure of what ur asking. But as far as emulating OO in C../..


Not emulating OO in C, rather using C with OO in mind.

Quote:
Original post by Ryan_001
../.. I know Mame uses a simple inheritance scheme for their hardware 'classes', all programmed in C. If you're masochistic u can peruse the source code here: www.mame.net ../.. I imagine most engines and/or software written in this way would be rather old stuff that was designed before C++ was around, or perhaps (as in Mame's case) there wasn't a lot of good C++ compilers available and in order to keep things portable stuck with plain old C.


Thanks that's also exactly the kind of information I'm looking for. If there are specific reason why C would still be used.

Perhaps some games and/or engines are targeted at some platforms where there are no ( or no good enough ) C++ compiler available. That would be one reason. Then the Object Oriented C approach makes sense here.

Do you think there would be any other reason ?

Quote:
Original post by Aldacron
C was used to create the server for Dark Age of Camelot. I've heard it was used in the renderer for Doom 3 (though the game itself is C++)../..


Thanks for the informations.

Quote:
Original post by Aldacron
../..The only way to know which current games are using C is to ask people who worked on them, unless the companies announced it somewhere../..


Actualy this is what I was secretly hopping :-)

Thanks again for your answers.


guy rabiller | President, CEO & CTO | m3factory
Way Walker
Way Walker
Quote:
Original post by Zahlman
Nobody really agrees on what this "OO" thingy means, anyway, so the question is somewhat ill-formed.


After reading this, I think I like the Nygaard classification. To think of the system as being built from lego-bricks really does seem to be the essence of OO programming. To define OO programming as encapsulation/polymorphism/inheritance/foo means the win32 API is OO, C is OO, Haskell is OO, etc. Really, using these terms seems to be defining OO as good programming practice. Good programming in all paradigms is based on encapsulation/polymorphism/inheritance/foo; the difference is how one acheives encapsulation/polymorphism/inheritance/foo or, rather, how one views program execution. If you picture it as black boxes each doing their thing all linked together for a common task, it's object oriented. If you picture it as transforming input into output, it's functional. If you picture it as a sequence of steps, it's procedural.

The benefit of OO isn't in applying good programming practice, it's in reasoning about what's happening. The reason some find functional techniques more confusing than OO isn't because the former lacks encapsulation/polymorphism/inheritance/foo, it's because those people find the model for acheiving encapsulation/polymorphism/inheritance/foo with functional techniques less transparent.

EDIT: It's interesting that this confusion of defining OO as good practice appears in the linked article:
Quote:

All other OO languages are continually compared to Smalltalk as the gold standard of what OO is.

  • There are many of us who like Smalltalk, and think it a fine language--even a groundbreaking language. But some of us tire of seeing it decorated with such wholly-uncritical, absolute superlatives. The gold standard? Please. There are many application domains where I wouldn't go near Smalltalk, even if there were no political or economic obstacles to its use. (And others where it would easily be my first choice). Anyone who is not a Smalltalker (indeed, anyone not familiar with a whole bunch of languages) ought to be careful making such grand sweeping statements. It's bad enough when it comes from the SmugSmalltalkWeenies... :)

    • He said the gold standard of object-orientation, nothing else, not the gold standard for general purpose languages or systems programming or embedded devices or whatever.





[Edited by - Way Walker on October 31, 2006 12:13:43 PM]
ajas95
ajas95
Hi, I've been working with the Dark Alliance engine for a couple years, and it is all C interfaces. For the most part, the C struct pointer is passed as the first argument where C++ would pass a this pointer, a lot like the ODE physics library interface.

The main advantage is that everything is precomputed in tools. There's no allocating or deleting these things... An asset comes off disc and you cast a pointer to the beginning of a block of data, adjust a few offsets to be pointers to blocks of internal data. There's no need for constructors to initalize or allocate memory nor destructors to deallocate.

That's a pretty benefit of C when it comes to cross platform... it's easy to get GCC and MSVC to generate a memory-identical C struct, but throw in vtables or rtti and you're out of luck. Many scripting languages can interface with C, but C++? Even ambitious compiled languages like 'D' gave up on C++ linkage because it was too bewildering.

Of course, the game written on top of the engine is C++. But even that I think is detrimental. C++ can be abused in new and amazing ways... mix in templates, operator overloads and implicit casts and you've got another AI genius with a grand plan.
andy_boy
andy_boy
This book my be of interest to you.

http://www.amazon.com/Programming-Abstractions-Course-Computer-Science/dp/0201545411/sr=8-1/qid=1162348633/ref=sr_1_1/102-9875542-8978555?ie=UTF8&s=books
JasonBlochowiak
JasonBlochowiak
Quote:
Original post by ajas95
Hi, I've been working with the Dark Alliance engine for a couple years, and it is all C interfaces. For the most part, the C struct pointer is passed as the first argument where C++ would pass a this pointer, a lot like the ODE physics library interface.

The main advantage is that everything is precomputed in tools. There's no allocating or deleting these things... An asset comes off disc and you cast a pointer to the beginning of a block of data, adjust a few offsets to be pointers to blocks of internal data. There's no need for constructors to initalize or allocate memory nor destructors to deallocate.

That's a pretty benefit of C when it comes to cross platform... it's easy to get GCC and MSVC to generate a memory-identical C struct, but throw in vtables or rtti and you're out of luck. Many scripting languages can interface with C, but C++? Even ambitious compiled languages like 'D' gave up on C++ linkage because it was too bewildering.

Of course, the game written on top of the engine is C++. But even that I think is detrimental. C++ can be abused in new and amazing ways... mix in templates, operator overloads and implicit casts and you've got another AI genius with a grand plan.



Um, in addition to doing pointer fixup all you need to do to re-hydrate most C++ classes is patch in an up-to-date vtable, so long as you don't intentionally shoot yourself in the foot. Not real hard.

To answer OPs question, yes, there are games out there that do things like manual vtables and whatnot in C.
Zahlman
Zahlman
Quote:
Original post by JasonBlochowiak
Um, in addition to doing pointer fixup all you need to do to re-hydrate most C++ classes is patch in an up-to-date vtable, so long as you don't intentionally shoot yourself in the foot. Not real hard.


Interface/Implementation Separation Man says, "What's a vtable?" [smile]
JasonBlochowiak
JasonBlochowiak
Quote:
Original post by Zahlman
Quote:
Original post by JasonBlochowiak
Um, in addition to doing pointer fixup all you need to do to re-hydrate most C++ classes is patch in an up-to-date vtable, so long as you don't intentionally shoot yourself in the foot. Not real hard.


Interface/Implementation Separation Man says, "What's a vtable?" [smile]


Mr. Pragmatism replies "It's the implementation detail that's handled when implementing the Rehydrate() interface (which knows the concrete target class), of course!" [wink]

On a slightly more serious note, I don't generally find myself trying to match structure conventions across different compilers and whatnot for the same platform - I expect that I'll have some generic cross platform binary data, but that the bulk of my resources will be platform specific lumps of binary data that have been maximally processed to be ready to use.

I don't actually rehydrate full C++ classes, rather I pass binary resources to create the class, with the class ctor consisting of whatever remaining bits of wiring are necessary to put the resource into play, plus all the actual functions to make use of the thing-that-needed-a-resource.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.