I am planning to develop an application in C. My programming experience has always been with object oriented languages. Hence I always think in terms of classes, interfaces, inheritance, polymorphism, etc, when designing an application.
All the C books I've looked at deal with how to program in C or focus on a particular topic, I couldn't find any that talk about application architecture in C. So how do you structure a C application when the OOP features are not available? How do you keep everything modular and well organized and avoid code duplication (no OOP seems like there will be alot of code duplication)?
Edit:
I am not looking for answers on 'how to write OOP code in C'. I am looking for the standard practice way of structuring C applications so they are modular and well organized. If the standard practice way is to hack on some OOP features then that is fair enough but if its not then there is no point in telling me to go down that route.
It is a different way of thinking. The core philosophy of C can be summarised as:
data + algorithms = programs
So to design an application in C:
You need to think carefully about what the data is, and define structs which reflect that well, and facilitate the relationships between different views on the data.
You need to think about what algorhythms are going to operate on what data, and what data they produce. This helps to clarify the structs you should have, and help to show what should be blocked together to create reusable blocks of code.
One way of moving to this approach from an OOP approach is to imagine that one struct + one .c file = a class, and to put in the .h file the struct definition and the externally accessible functions (public methods).
You have to write a lot of code to do boring things like memory allocation and freeing and all that jazz. It's not as bad as it sounds, but factor this into your design.
you can design your C project as oriented object project and then replace the class by structure. this was recommended to me in this topic and in this topic
Also, to create re-usable C software, read this book by David R. Hanson
https://sites.google.com/site/cinterfacesimplementations/
Basic OOP is best done with the techniques mentioned in Alex Schriner's OOC.pdf book
First you will identify the components and their interactions to solve the problem.
then inside each component, below practices can be used.
Design the public functions first.
design the data structure ( i.e struct ) the functions are going to work
Modify the public functions to take the corresponding structure as pointer argument. [ There is no instance variable concept in c. you need to define a structure and pass structure between functions ] .
group the functions with related data structure in a header file.
provide the implementations to the public functions in a separate c file which includes the header file you defined.
make all your private/helper methods as static, so they will not be visible to other c files.
Since there is no namespace concept in C, Ensure your public functions are not conflicted with existing library functions. some people are using name mangling like {short name of header file}_{function name}
allocating and release the memory is the developers responsibility. it is better to have initialize and free functions to allocate and clear the memory along with the public functions designed.
Follow the coding styles you are comfortable with.
Design each components as shared library , so that you don't need to compile them every time.
It is possible to practice TDD with C, see C programming and TDD .
If you're used to practicing TDD, you know it will help you keep your code well organized and modular.
Related
For a project I'm working on, there are a number of states where calculations can be relied upon to return the same results (and have no side effects). The obvious solution would be to use memoization for all the costly functions.
I would need to have memoization that handles more than one state (so that I could invalidate one cache set without invalidating another). Does anybody know a good C library for this sort of thing? (Note that it can't be C++, we're talking C.)
I've worked with some good implementations in Python that use decorators to be able to flexibly memoize a bunch of different functions. I'm kind of wondering is there's a generic library that could do similar things with C (though probably with explicit function wrapping rather than convenient syntax). I just think it would be silly to have to add caching to each function individually when it's a common enough issue there must be some off-the-shelf solutions for it.
The characteristics I would look for are the following:
Can cache functions with various types of input and output
Manages multiple different caches (so you can have short-term and long term caching)
Has good functions for invalidating caches
Intended to be used by wrapping functions, rather than altering existing functions
Anybody know a C implementation that can handle all or most of these requisites?
Okay, seeing as there were no memoization libraries for C and I was looking for a drop-in solution for memoizing existing C functions in a code base, I made my own little memoization library that I'm releasing under the APL 2.0. Hopefully people will find this useful and it won't crash and burn on other compilers. If it does have issues, message me here and I'll look into it whenever I have the time (which would probably be measured in increments of months).
This library is not built for speed, but it works and has been tested to make sure it is fairly straightforward to use and doesn't display any memory leaks in my testing. Fundamentally, this lets me add memoization to functions similar to the decorator pattern that I'm used to in Python.
The library is currently on SourceForge as the C-Memo Library. It comes with a little user manual and a couple of 3rd party permissively licensed libraries for generic hashing. If the location changes, I'll try to update this link. I found this helpful in working on my project, hopefully others will find it useful for their projects.
memoization is all but built into the haskell language. You can call this functionality from c
Update:
I'm still learning about functional programming, but I do know that memoization is fairly common in functional programming becuase the language features make it easy. I'm learning f#. I don't know haskell, but it is the only functional language I know of that will interact with c. You might be able to find another functional programming language that interfaces with c in a more suitable fashion than what haskell provides.
Why, just can't be C++?
Just for a starting point look to this memoization function:
declaration:
template<typename T, typename F>
auto Memoize(T key, F function) {
static T memory_key = key;
static auto memory = function(memory_key);
if (memory_key != key) {
memory_key = key;
memory = function(memory_key);
}
return memory;
}
Usage example:
auto index = Memoize(value, IndexByLetter);
I have been doing OOP (C++/Java/PHP/Ruby) for a long time and really have a hard time imagining how large programs and libraries such as Linux or Apache can be written entirely in an imperative style. What would be small open source C projects I could look at to get a feel of how things are done in C?
Bonus points if the project is hosted on GitHub.
Things are done exactly the same way in C, but with less overt support from the language. Instead of creating a class to encapsulate some state, you create a struct. Instead of creating class members, with implicit this parameters, you create functions that you explicitly pass a struct* as the first parameter, that then operate on the struct.
To ensure that encapsulation is not broken you can declare the struct in a header, but only define it in the .c file where it is used. Virtual functions require more work - but again, its just a case of putting function pointers in the struct. Which is actually more convenient in C than C++ because in C you get to fill in your vtables manually, getting quite a fine level of control over which part of code implements part of what COM interface (if you are into COM in C of course).
You might find the ccan (Comprehensive C Archive Network, modeled after Perl's CPAN) interesting.
It's small at the moment, but the contributions are of high quality. Many of the contributions are by linux kernel developers.
Almost everything in there falls into the "few thousand LOC" or less category, too.
If you want a small example to start with, try looking at the source for the basic Linux CLI utilities. GNU binutils, make, or any of the other GNU utilities have full source code available and are relatively small code bases (some are larger than others). The easiest thing is usually to start with a utility that you have used before and are already familiar with.
Look at GLib for an almost canonical example of how to do object oriented programming in C.
Does the FILE type used through standard C functions fopen, etc. have an object-oriented interface?
I'm looking for opinions with reasoning rather than an absolute answer, as definitions of OO vary by who you ask. What are the important OO concepts it meets or doesn't meet?
In response to JustJeff's comment below, I am not asking whether C is an OO language, nor whether C (easily or not) allows OO programming. (Isn't that a separate issue?)
Is C an object-oriented language?
Was OOP (object-oriented-programming) anything more than a laboratory concept when C and FILE were created?
Answering these questions will answer your question.
EDIT:
Further thoughts:
Object Oriented specifically means several behaviors, including:
Inheritence: Can you derive new classes from FILE?
Polymorphism: Can you treat derived classes as FILEs?
Encapsulation: Can you put a FILE inside another object?
Methods & Properties: Does a FILE have methods and properties specific to it? (eg.
myFile.Name, myFile.Size, myFile.Delete())
Although there are well known C "tricks" to accomplish something resembling each of these behaviors, this is not built in to FILE, and is not the original intent.
I conclude that FILE is not Object Oriented.
If the FILE type were "object oriented", presumably we could derive from it in some meaningful way. I've never seen a convincing instance of such a derivation.
Lets say I have new hardware abstraction, a bit like a socket, called a wormhole. Can I derive from FILE (or socket) to implement it. Not really - I've probably got to make some changes to tables in the OS kernel. This is not what I call object orientation
But this whole issue comes down to semantics in the end. Some people insist that anything that uses a jump-table is object oriented, and IBM have always claimed that their AS/400 boxes are object-oriented, through & through.
For those of you that want to dip into the pit of madness and stupidity that is the USENET comp.object newsgroup, this topic was discussed quite exhaustively there a few years ago, albeit by mad and stupid people. If you want to trawl those depths, the Google Groups interface is a good place to start.
Academically speaking, certainly the actual files are objects. They have attributes and you can perform actions on them. Doesn't mean FILE is a class, just saying, there are degrees of OO-ness to think about.
The trouble with trying to say that the stdio FILE interface qualifies as OO, however, is that the stdio FILE interface doesn't represent the 'objectness' of the file very well. You could use FILEs under plain old C in an OO way, but of course you forfeit the syntactic clarity afforded by Java or C++.
It should probably further be added that while you can't generate 'inheritance' from FILE, this further disqualifies it as OO, but you could argue that's more a fault of its environment (plain C) than the abstract idea of the file-as-object itself.
In fact .. you could probably make a case for FILE being something like a java interface. In the linux world, you can operate almost any kind of I/O device through the open/close/read/write/ioctl calls; the FILE functions are just covers on top of those; therefore in FILE you have something like an abstract class that defines the basic operations (open/read/etc) on an 'abstact i/o device', leaving it up to the various sorts of derived types to flesh those out with type-specific behavior.
Granted, it's very hard to see the OO in a pile of C code, and very easy to break the abstractions, which is why the actual OO languages are so much more popular these days.
It depends. How do you define an "object-oriented interface"? As the comments to abelenky's post shows, it is easy to construct an argument that FILE is object-oriented. It depends on what you mean by "object-oriented". It doesn't have any member methods. But it does have functions specific to it.
It can not be derived from in the "conventional" sense, but it does seem to be polymorphic. Behind a FILE pointer, the implementation can vary widely. It may be a file, it may be a buffer in memory, it may be a socket or the standard output.
Is it encapsulated? Well, it is essentially implemented as a pointer. There is no access to the implementation details of where the file is located, or even the name of the file, unless you call the proper API functions on it. That sounds encapsulated to me.
The answer is basically whatever you want it to be. If you don't want FILE to be object-oriented, then define "object-oriented" in a way that FILE can't fulfill.
C has the first half of object orientated.
Encapsulation, ie you can have compound types like FILE* or structs but you can't inherit from them which is the second (although less important) half
No. C is not an object-oriented language.
I know that's an "absolute answer," which you didn't want, but I'm afraid it's the only answer. The reasoning is that C is not object-oriented, so no part of it can have an "object-oriented interface".
Clarification:
In my opinion, true object-orientation involves method dispatch through subtype polymorphism. If a language lacks this, it is not object-oriented.
Object-orientation is not a "technique" like GTK. It is a language feature. If the language lacks the feature, it is not object-oriented.
If object-orientation were merely a technique, then nearly every language could be called object-oriented, and the term would cease to have any real meaning.
There are different definitions of oo around. The one I find most useful is the following (inspired by Alan Kay):
objects hold state (ie references to other objects)
objects receive (and process) messages
processing a message may result in
messages beeing sent to the object itself or other objects
a change in the object's state
This means you can program in an object-oriented way in any imperative programming language - even assembler. A purely functional language has no state variables, which makes oo impossible or at least awkward to implement (remember: LISP is not pure!); the same should go for purely declarative languages.
In C, message passing in most often implemented as function calls with a pointer to a struct holding the object's state as first argument, which is the case for the file handling api. Still, C as a language can't be classified as oo as it doesn't have syntactic support for this style of programming.
Also, some other definitions of oo include things like class-based inheritance (so what about prototypal languages?) and encapsulation - which aren't really essential in my opinion - but some of them can be implemented in C with some pointer- and casting magic.
Having learned Java and C++, I've learned the OO-way. I want to embark on a fairly ambitious project but I want to do it in C. I know how to break problems down into classes and how to turn them into class hierarchies. I know how to abstract functionality into abstract classes and interfaces. I'm even somewhat proficient at using polymorphism in an effective way.
The problem is that when I'm presented with a problem, I only way I know how to do it is in an Object-Oriented way. I've become too dependent on Object-Oriented design philosophies and methodologies.
I want to learn how to think in a strictly procedural way. How do I do things in a world that lacks classes, interfaces, polymorphism, function overloading, constructors, etc.
How do you represent complex concepts using only non-object-oriented structs? How do you get around a lack of function overloading? What are some tip and tricks for thinking in a procedural way?
The procedural way is to, on one side, have your data structures, and, on the other, your algorithms. Then you take your data structures and pass them to your algorithms. Without encapsulation, it takes a somewhat higher amount of discipline to do this and if you increase the abstraction level to make it easier to do it right, you're doing a considerable part of OO in C.
I think you have a good plan. Doing things the completely OO way in C, while quite possible, is enough of a pain that you would soon drop it anyway. (Don't fight the language.)
If you want a philosophical statement on mapping the OO way to the C way, in part it happens by pushing object creation up one level. A module can still implement its object as a black box, and you can still use reasonable programming style, but basically its too much of a pain to really hide the object, so the caller allocates it and passes it down, rather than the module allocating it and returning it back up. You usually punt on getters and setters, or implement them as macros.
Consider also that all of those abstractions you mentioned are a relatively thin layer on top of ordinary structs, so you aren't really very far away from what you want to do. It just isn't packaged quite as nicely.
The C toolkit consists of functions, function pointers and macros. Function pointers can be used to emulate polymorphism.
You are taking the reverse trip old C programmers did for learning OO.
Even before c++ was a standart OO techniquis were used in C.
They included defining structs with a pointer to srtuct (usually called this...)
Then defining pointer functions in the struct, and during runtime initialize those pointers to the relevant functions.
All those functions received as first paremeter the struct pointer this.
Don't think C in the complete OOP way. If you have to use C, you should learn procedural programming. Doing this would not take more time than learning how to realize all the OOP features in C. Furthermore, basic encapsulation is probably fine, but a lot of other OOP features come with overhead on performance when you mimic them (not when the language is designed to support OOP). The overhead may be huge if you strictly follow the C++ design methodology to represent every small things as objects. Programming languages have specific purposes in design. When you break the boundary, you always have to pay something as the cost.
Don't think you have to shelve your knowledge of object-oriented work - you can "program into the language".
I had to work in C after being primarily experienced in object-oriented work. C allows for some level of object concepts to pull through. At the job, I had to implement a red-black tree in C, for use in a sweep-line algorithm to find the intersection points in a set of segments. Since the algorithm used different comparison functions, I ended up using function pointers to achieve the same effect as lambdas in Scheme or delegates in C#. It worked well, and also allowed the balanced tree to be reusable.
The other feature of the balanced tree was using void pointers to store arbitrary data. Again, void and function pointers in C are a pain (if you don't know their ins and outs), but they can be used to approximate creating a generic data structure.
One final note: use the right tool for the job. If you want to use C simply to master procedural technique, then choose a problem that is well-suited to a procedural approach. I didn't have a choice in the matter (legacy application written in C, and people demand the world and refuse to enter the 21st century), so I had to be creative. C is great for low/medium abstractions from the machine, say if you wanted to write a command-line packet inspection program.
The standard way to do polymorphic behavior in C is to use function pointers. You'll find a lot of C APIs (such as the standard qsort(3) and bsearch(3)) take function pointers as parameters; some non-standard ones such as qsort_r take a function pointer and a context pointer (thunk in this case) which serves no purpose other than to be passed back to the callback function. The context pointer functions exactly like the this pointer in object-oriented languages, when dealing with function objects (e.g. functors).
See also:
Can you write object-oriented code in C?
Object-Orientation in C
Try not to use OOP in C. But if you need to, use structures. For the functions,
take a structure for an argument, like so:
typedef struct{
int age;
char* name;
char* dialog;
} Human;
void make_dialog(Human human){
char* dialog="Hi";
human.dialog=dialog;
}
which works exactly like python's self, or something like that and to access other functions belonging to that class:
void get_dialog(Human human){
make_dialog(human);
printf(human.dialog);
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have little more than beginner-level C skills and would like to know if there are any de facto "standards" to structure a somewhat complex application in C. Even GUI based ones.
I have been always using the OO paradigm in Java and PHP and now that I want to learn C I'm afraid that I might structure my applications in the wrong way. I'm at a loss on which guidelines to follow to have modularity, decoupling and dryness with a procedural language.
Do you have any readings to suggest? I couldn't find any application framework for C, even if I don't use frameworks I've always found nice ideas by browsing their code.
The key is modularity. This is easier to design, implement, compile and maintain.
Identify modules in your app, like classes in an OO app.
Separate interface and implementation for each module, put in interface only what is needed by other modules. Remember that there is no namespace in C, so you have to make everything in your interfaces unique (e.g., with a prefix).
Hide global variables in implementation and use accessor functions for read/write.
Don't think in terms of inheritance, but in terms of composition. As a general rule, don't try to mimic C++ in C, this would be very difficult to read and maintain.
If you have time for learning, take a look at how an Ada app is structured, with its mandatory package (module interface) and package body (module implementation).
This is for coding.
For maintaining (remember that you code once, but you maintain several times) I suggest to document your code; Doxygen is a nice choice for me. I suggest also to build a strong regression test suite, which allows you to refactor.
It's a common misconception that OO techniques can't be applied in C. Most can -- it's just that they are slightly more unwieldy than in languages with syntax dedicated to the job.
One of the foundations of robust system design is the encapsulation of an implementation behind an interface. FILE* and the functions that work with it (fopen(), fread() etc.) is a good example of how encapsulation can be applied in C to establish interfaces. (Of course, since C lacks access specifiers you can't enforce that no-one peeks inside a struct FILE, but only a masochist would do so.)
If necessary, polymorphic behaviour can be had in C using tables of function pointers. Yes, the syntax is ugly but the effect is the same as virtual functions:
struct IAnimal {
int (*eat)(int food);
int (*sleep)(int secs);
};
/* "Subclass"/"implement" IAnimal, relying on C's guaranteed equivalence
* of memory layouts */
struct Cat {
struct IAnimal _base;
int (*meow)(void);
};
int cat_eat(int food) { ... }
int cat_sleep(int secs) { ... }
int cat_meow(void) { ... }
/* "Constructor" */
struct Cat* CreateACat(void) {
struct Cat* x = (struct Cat*) malloc(sizeof (struct Cat));
x->_base.eat = cat_eat;
x->_base.sleep = cat_sleep;
x->meow = cat_meow;
return x;
}
struct IAnimal* pa = CreateACat();
pa->eat(42); /* Calls cat_eat() */
((struct Cat*) pa)->meow(); /* "Downcast" */
All good answers.
I would only add "minimize data structure". This might even be easier in C, because if C++ is "C with classes", OOP is trying to encourage you to take every noun / verb in your head and turn it into a class / method. That can be very wasteful.
For example, suppose you have an array of temperature readings at points in time, and you want to display them as a line-chart in Windows. Windows has a PAINT message, and when you receive it, you can loop through the array doing LineTo functions, scaling the data as you go to convert it to pixel coordinates.
What I have seen entirely too many times is, since the chart consists of points and lines, people will build up a data structure consisting of point objects and line objects, each capable of DrawMyself, and then make that persistent, on the theory that that is somehow "more efficient", or that they might, just maybe, have to be able to mouse over parts of the chart and display the data numerically, so they build methods into the objects to deal with that, and that, of course, involves creating and deleting even more objects.
So you end up with a huge amount of code that is oh-so-readable and merely spends 90% of it's time managing objects.
All of this gets done in the name of "good programming practice" and "efficiency".
At least in C the simple, efficient way will be more obvious, and the temptation to build pyramids less strong.
The GNU coding standards have evolved over a couple of decades. It'd be a good idea to read them, even if you don't follow them to the letter. Thinking about the points raised in them gives you a firmer basis on how to structure your own code.
If you know how to structure your code in Java or C++, then you can follow the same principles with C code. The only difference is that you don't have the compiler at your side and you need to do everything extra carefully manually.
Since there are no packages and classes, you need to start by carefully designing your modules. The most common approach is to create a separate source folder for each module. You need to rely on naming conventions for differentiating code between different modules. For example prefix all functions with the name of the module.
You can't have classes with C, but you can easily implement "Abstract Data Types". You create a .C and .H file for every abstract data type. If you prefer you can have two header files, one public and one private. The idea is that all structures, constants and functions that need to be exported go to the public header file.
Your tools are also very important. A useful tool for C is lint, which can help you find bad smells in your code. Another tool you can use is Doxygen, which can help you generate documentation.
Encapsulation is always key to a successful development, regardless of the development language.
A trick I've used to help encapsulate "private" methods in C is to not include their prototypes in the ".h" file.
I'd suggets you to check out the code of any popular open source C project, like... hmm... Linux kernel, or Git; and see how they organize it.
The number rule for complex application: it should be easy to read.
To make complex application simplier, I employ Divide and conquer.
I would suggest reading a C/C++ textbook as a first step. For example, C Primer Plus is a good reference. Looking through the examples would give you and idea on how to map your java OO to a more procedural language like C.