Alternative to reference virtual table in C without using function pointers. - c

I am taking advantage of polymorphism in C by using virtual tables as described in Polymorphism (in C) and it works great.
Unfortunately, the limitation of my current project does not allow me to use function pointer or reference to structs in some part of my code. As a consequence, I cannot use the original approach directly.
In the mentioned approach, the base "class/struct" has a member that points to the virtual table. In order to get ride of this pointer, I decided to replace it with an enumerate that acts as key to access the virtual table.
It works but I wonder if if is the best solution. Do you come up with any alternative that fits better than my proposal?
/**
* This example shows a common approach to achive polymorphism in C and an
* alternative that does NOT include a reference to function pointer in the
* base
* class.
**/
#include<stdio.h>
// some functions to make use of polymorphism
void funBase1()
{
printf("base 1 \n");
}
void funBase2()
{
printf("base 2 \n");
}
void funDerived1()
{
printf("derived 1 \n");
}
void funDerived2()
{
printf("derived 2 \n");
}
// struct to host virtual tables
typedef struct vtable {
void (*method1)(void);
void (*method2)(void);
}sVtable;
// enumerate to access the virtual table
typedef enum {BASE, DERIVED} eTypes;
// global virtual table used for the alternative solution
const sVtable g_vtableBaseAlternative[] = {
{funBase1, funBase2},
{funDerived1, funDerived2}, };
// original approach that i cannot use
typedef struct base {
const sVtable* vtable;
int baseAttribute;
}sBase;
// alternative approach
typedef struct baseAlternative {
const eTypes vtable_key;
int baseAttribute;
}sBaseAlternative;
typedef struct derived {
sBase base;
int derivedAttribute;
}sDerived;
// original way to use
static inline void method1(sBase* base)
{
base->vtable->method1();
}
const sVtable* getVtable(const int key, const sVtable* vTableDic)
{
return &vTableDic[key];
}
// Alternative to get a reference to the virtual table
static inline void method1Aternative(sBaseAlternative* baseAlternative)
{
const sVtable* vtable;
vtable = getVtable(baseAlternative->vtable_key, g_vtableBaseAlternative);
printf("alternative version: ");
vtable->method1();
}
int main() {
const sVtable vtableBase[] = { {funBase1, funBase2} };
const sVtable vtableDerived[] = { {funDerived1, funDerived2} };
sBase base = {vtableBase, 0 };
sBase derived = {vtableDerived, 1 };
sBaseAlternative baseAlternative = {DERIVED, 1 };
method1(&base);
method1(&derived);
method1Aternative(&baseAlternative);
}

my current project does not allow me to use function pointer or reference to structs
You could use an array of T (any type you like) to represent a data type. For example, I tend to use arrays of unsigned char to serialise and deserialise my data structures for web transfer... Let's for example assume you're using sprintf and sscanf for serialisation and deserialisation (which you shouldn't really do, but they're okay for demos)... Instead of struct arguments, you use char * arguments, and you use sscanf to read that data to local variables, sprintf to modify it... that covers the no reference to structs allowed problem.
With regards to the function pointer problem, you could combine all of your functions into one which switches on... a tagged structure in string form... Here's a simple (yet incomplete) example involving two candidates for classes: a length-prefixed string which uses two bytes to encode the length and kind of derives from C-string behaviour, and a C string.
enum { fubar_is_string, fubar_is_length_prefixed_string };
typedef unsigned char non_struct_str_class;
size_t non_struct_strlen(non_struct_str_class *fubar) {
size_t length = 0;
switch (fubar++[0]) {
case fubar_is_length_prefixed_string:
length = fubar++[0];
length <<= 8;
length += fubar++[0];
// carry through into the next case
// to support strings longer than 64KB
case fubar_is_string: if (!length)
length = strlen(fubar);
/* handle fubar as string */
}
return length;
}
C is a turing complete programming language, so of course it can be used to mimic object oriented polymorphism... but it's far better at mimicking procedural polymorphism, or in some cases even functional polymorphism... As an example, you could say qsort and bsearch use a primitive form of parametric polymorphism similar to that of map (even more similar to a filter idiom).
You could also use _Generic with limited success, for example as the C11 standard does by providing a generic cbrt macro for all of the standard floating point types:
#define cbrt(X) _Generic((X), \
long double: cbrtl, \
default: cbrt, \
float: cbrtf \
)(X)
The preprocessor is particularly useful if you're going to go the route of mimicry... You might be interested in the C11 book by Klemens.

I am taking advantage of polymorphism in C
you do not of course. You only create a prothesis of it. IMO the simulation of objects in C is the worst possible solution. If you prefer the OOP paradigm - use the OO language. In this case C++.
Answering your question - you can't do it (sane way) without the function pointers.
I discourage people from attempts of OOP like programming in the procedural languages. It usually leads to the less readable, error prone and very difficult to maintain programs.
Choose the correct tool (the language is the tool) for the task and the method.
It is like using the knife instead of screwdriver. You can, but the screwdriver will definitely be much better.

Related

How do I write a genric display function in C to display void pointers of all data types?

I've been using void pointers to implement stacks using arrays. I know that before displaying the value pointed to by the void pointer, we need to cast it to suitable data type.
This is my stack structure
typedef struct {
void **arr; // array stack
int size; // size of the stack
int top; // top most element of the stack
int count; // number of elements in the stack
} stack_T;
Say I've an int stack ( contents of stack -> arr is of data type int )
now. To display it's contents I can simply write a display()
void displayIntStack( stack_T *stack ) {
while ( !isEmpty( stack )) {
printf( "%d ", *( int * )stack -> arr[ stack -> top] );
pop( stack );
}
}
I can call it using displayIntStack( stack ); and it'll display the contents of the int stack.
If I want to implement more generic display() function to display the stack contents of all data types without the need to write separate functions. How would I do it?
If I want to implement more generic display() function to display the stack contents of all data types without the need to write separate functions. How would I do it?
Add a member to stack_T that is a function pointer that does the printing. Set that .print() member when defining the stack instance.
typedef struct {
void **arr;
int size;
int top;
int count;
int (*print)(void *);
} stack_T;
while (!isEmpty(stack)) {
stack->print(stack->arr[stack->top]);
pop(stack);
}
You can provide a predefined set of .print() functions for int, double and the usual suspects. This approach lets the user create custom print functions for any type.
I'd also expect a way to apply this .print() to the stack without changing the stack.
Further: I think the best approach is to form an apply function for your stack type and negating the need for a .print() function member:
Pseudo code
int stack_apply(const stack_T *st, int (*f)(void *state, void *data), void *state) {
for each node i in the stack
int result = f(state, stack->arr[i]);
if (result) return result;
}
return 0;
}
Now when you want to print:
stack_apply(st, my_print_function, my_print_state);
Or maybe a search function, or a max function, or a standard deviation function ....
From C17 standard document, Generic selection (6.5.1.1, page number: 56-57):
You can use type-generic expression:
#define cbrt(X) _Generic((X), \
long double: cbrtl, \
default: cbrt, \
float: cbrtf \
)(X)
Let's assume, there are these functions :
displayIntStack(stack,int), displayFloatStack(stack,float), displayCharStack(stack, char).
Then, we define one function displayStack(stack,type) in the main().
#define displayStack(stack,type) _Generic((type), int: displayIntStack, float: displayFloatStack, char:displayCharStack)(stack,type)
int main() {
displayStack(stack,1); // calls displayIntStack
displayStack(stack,1.2f); // calls displayFloatStack
displayStack(stack,'c'); // calls char:displayCharStack
}
Another way : Using macro function
#define displayStack(stack_T *stack, T) \
{ \
while (!isEmpty(stack)) \
{ \
printf("%d ", *(T *)stack->arr[stack->top]);\
pop(stack); \
} \
}
displayStack(stack_T *stack, int) ; // For integer data
displayStack(stack_T *stack, float) ; // for float data
displayStack(stack_T *stack, double) ; // For double data
displayStack(stack_T *stack, char) ; // For char data
Hmm maybe void pointer ? It will allow you to pass pointer to any kind of type;) then just parse and print the value hidden behind pointer
How do I write a generic display function in C to display void pointers of all data types?
You cannot do that reliably, unless your display function is given some way of display values. And mostly because C types are not known at run-time (they are erased): the same sequence of bits could be a char* string or some array of double-s (perhaps even inside some union). Consider perhaps learning Ocaml which has a stricter and somehow safer type system (and retain some type information at runtime).
BTW, you could store inside your "generic" stack_T both the sizeof and the alignof pointed values. Then you could have, with some coding pain, one less indirection by using flexible array members. This might be more efficient (in some cases) because of your CPU cache.
A possibility might be to pass a callback function to your display function. You could for example pass as argument a function pointer displaying the pointed values.
Declare first (for readability) a signature
typedef void element_display_sigt (void*displayed_data);
Then declare your displaying function to take such a function pointer
void display_stack(stack_T *stack, element_display_sigt*dispfun);
Actually, what you dream of are closures. They don't exist in C17. Check by reading n2176 (a draft C standard) and Modern C
In practice, your element_display_sigt would often take an extra argument, for example a FILE* to write to. And your display_stack would also have that extra argument.
FWIW, closures exist (and also anonymous functions) in modern C++, in Scheme, in Common Lisp, in Ocaml, in Haskell, in Lua. I heard that future C standards might add anonymous functions to C.
You could consider embedding an interpreter like Lua or GNU Guile (a nice Scheme implementation) in your application coded in C.
You might be interested in reading the Dragon book, about λ-calculus, and about garbage collection.
If you code for Linux, be aware of dlopen(3) and dlsym(3) : in some cases, it might be worthwhile to generate the C code of some plugin at runtime, then compile that code into a shared object library, then use that dlopen-ed plugin or shared object at runtime. My manydl.c example shows that this can be done thousands of times. Another possibility might be to use machine code generation libraries like GNU lightning or libgccjit.
Be also aware that GNU libc specifically still has (at end of 2020) a way of customizing printf
Another approach is to generate some (printing) C code at build time, with tools inspired from SWIG. You could either write your own GCC plugin generating printing code or, using GNU bison, write your own C code generator.

Writing object oriented code in C [duplicate]

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 6 years ago.
Improve this question
What are some ways to write object-oriented code in C? Especially with regard to polymorphism.
See also this Stack Overflow question Object-orientation in C.
Yes. In fact Axel Schreiner provides his book "Object-oriented Programming in ANSI-C" for free which covers the subject quite thoroughly.
Since you're talking about polymorphism then yes, you can, we were doing that sort of stuff years before C++ came about.
Basically you use a struct to hold both the data and a list of function pointers to point to the relevant functions for that data.
So, in a communications class, you would have an open, read, write and close call which would be maintained as four function pointers in the structure, alongside the data for an object, something like:
typedef struct {
int (*open)(void *self, char *fspec);
int (*close)(void *self);
int (*read)(void *self, void *buff, size_t max_sz, size_t *p_act_sz);
int (*write)(void *self, void *buff, size_t max_sz, size_t *p_act_sz);
// And data goes here.
} tCommClass;
tCommClass commRs232;
commRs232.open = &rs232Open;
: :
commRs232.write = &rs232Write;
tCommClass commTcp;
commTcp.open = &tcpOpen;
: :
commTcp.write = &tcpWrite;
Of course, those code segments above would actually be in a "constructor" such as rs232Init().
When you 'inherit' from that class, you just change the pointers to point to your own functions. Everyone that called those functions would do it through the function pointers, giving you your polymorphism:
int stat = (commTcp.open)(commTcp, "bigiron.box.com:5000");
Sort of like a manual vtable.
You could even have virtual classes by setting the pointers to NULL -the behaviour would be slightly different to C++ (a core dump at run-time rather than an error at compile time).
Here's a piece of sample code that demonstrates it. First the top-level class structure:
#include <stdio.h>
// The top-level class.
typedef struct sCommClass {
int (*open)(struct sCommClass *self, char *fspec);
} tCommClass;
Then we have the functions for the TCP 'subclass':
// Function for the TCP 'class'.
static int tcpOpen (tCommClass *tcp, char *fspec) {
printf ("Opening TCP: %s\n", fspec);
return 0;
}
static int tcpInit (tCommClass *tcp) {
tcp->open = &tcpOpen;
return 0;
}
And the HTTP one as well:
// Function for the HTTP 'class'.
static int httpOpen (tCommClass *http, char *fspec) {
printf ("Opening HTTP: %s\n", fspec);
return 0;
}
static int httpInit (tCommClass *http) {
http->open = &httpOpen;
return 0;
}
And finally a test program to show it in action:
// Test program.
int main (void) {
int status;
tCommClass commTcp, commHttp;
// Same 'base' class but initialised to different sub-classes.
tcpInit (&commTcp);
httpInit (&commHttp);
// Called in exactly the same manner.
status = (commTcp.open)(&commTcp, "bigiron.box.com:5000");
status = (commHttp.open)(&commHttp, "http://www.microsoft.com");
return 0;
}
This produces the output:
Opening TCP: bigiron.box.com:5000
Opening HTTP: http://www.microsoft.com
so you can see that the different functions are being called, depending on the sub-class.
Namespaces are often done by doing:
stack_push(thing *)
instead of
stack::push(thing *)
To make a C struct into something like a C++ class you can turn:
class stack {
public:
stack();
void push(thing *);
thing * pop();
static int this_is_here_as_an_example_only;
private:
...
};
Into
struct stack {
struct stack_type * my_type;
// Put the stuff that you put after private: here
};
struct stack_type {
void (* construct)(struct stack * this); // This takes uninitialized memory
struct stack * (* operator_new)(); // This allocates a new struct, passes it to construct, and then returns it
void (*push)(struct stack * this, thing * t); // Pushing t onto this stack
thing * (*pop)(struct stack * this); // Pops the top thing off the stack and returns it
int this_is_here_as_an_example_only;
}Stack = {
.construct = stack_construct,
.operator_new = stack_operator_new,
.push = stack_push,
.pop = stack_pop
};
// All of these functions are assumed to be defined somewhere else
And do:
struct stack * st = Stack.operator_new(); // Make a new stack
if (!st) {
// Do something about it
} else {
// You can use the stack
stack_push(st, thing0); // This is a non-virtual call
Stack.push(st, thing1); // This is like casting *st to a Stack (which it already is) and doing the push
st->my_type.push(st, thing2); // This is a virtual call
}
I didn't do the destructor or delete, but it follows the same pattern.
this_is_here_as_an_example_only is like a static class variable -- shared among all instances of a type. All methods are really static, except that some take a this *
I believe that besides being useful in its own right, implementing OOP in C is an excellent way to learn OOP and understand its inner workings. Experience of many programmers has shown that to use a technique efficiently and confidently, a programmer must understand how the underlying concepts are ultimately implemented. Emulating classes, inheritance, and polymorphism in C teaches just this.
To answer the original question, here are a couple resources that teach how to do OOP in C:
EmbeddedGurus.com blog post "Object-based programming in C" shows how to implement classes and single inheritance in portable C:
http://embeddedgurus.com/state-space/2008/01/object-based-programming-in-c/
Application Note ""C+"—Object Oriented Programming in C" shows how to implement classes, single inheritance, and late binding (polymorphism) in C using preprocessor macros:
http://www.state-machine.com/resources/cplus_3.0_manual.pdf, the example code is available from http://www.state-machine.com/resources/cplus_3.0.zip
I've seen it done. I wouldn't recommend it. C++ originally started this way as a preprocessor that produced C code as an intermediate step.
Essentially what you end up doing is create a dispatch table for all of your methods where you store your function references. Deriving a class would entail copying this dispatch table and replacing the entries that you wanted to override, with your new "methods" having to call the original method if it wants to invoke the base method. Eventually, you end up rewriting C++.
Sure that is possible. This is what GObject, the framework that all of GTK+ and GNOME is based on, does.
The C stdio FILE sub-library is an excellent example of how to create abstraction, encapsulation, and modularity in unadulterated C.
Inheritance and polymorphism - the other aspects often considered essential to OOP - do not necessarily provide the productivity gains they promise and reasonable arguments have been made that they can actually hinder development and thinking about the problem domain.
Trivial example with an Animal and Dog: You mirror C++'s vtable mechanism (largely anyway). You also separate allocation and instantiation (Animal_Alloc, Animal_New) so we don't call malloc() multiple times. We must also explicitly pass the this pointer around.
If you were to do non-virtual functions, that's trival. You just don't add them to the vtable and static functions don't require a this pointer. Multiple inheritance generally requires multiple vtables to resolve ambiguities.
Also, you should be able to use setjmp/longjmp to do exception handling.
struct Animal_Vtable{
typedef void (*Walk_Fun)(struct Animal *a_This);
typedef struct Animal * (*Dtor_Fun)(struct Animal *a_This);
Walk_Fun Walk;
Dtor_Fun Dtor;
};
struct Animal{
Animal_Vtable vtable;
char *Name;
};
struct Dog{
Animal_Vtable vtable;
char *Name; // Mirror member variables for easy access
char *Type;
};
void Animal_Walk(struct Animal *a_This){
printf("Animal (%s) walking\n", a_This->Name);
}
struct Animal* Animal_Dtor(struct Animal *a_This){
printf("animal::dtor\n");
return a_This;
}
Animal *Animal_Alloc(){
return (Animal*)malloc(sizeof(Animal));
}
Animal *Animal_New(Animal *a_Animal){
a_Animal->vtable.Walk = Animal_Walk;
a_Animal->vtable.Dtor = Animal_Dtor;
a_Animal->Name = "Anonymous";
return a_Animal;
}
void Animal_Free(Animal *a_This){
a_This->vtable.Dtor(a_This);
free(a_This);
}
void Dog_Walk(struct Dog *a_This){
printf("Dog walking %s (%s)\n", a_This->Type, a_This->Name);
}
Dog* Dog_Dtor(struct Dog *a_This){
// Explicit call to parent destructor
Animal_Dtor((Animal*)a_This);
printf("dog::dtor\n");
return a_This;
}
Dog *Dog_Alloc(){
return (Dog*)malloc(sizeof(Dog));
}
Dog *Dog_New(Dog *a_Dog){
// Explict call to parent constructor
Animal_New((Animal*)a_Dog);
a_Dog->Type = "Dog type";
a_Dog->vtable.Walk = (Animal_Vtable::Walk_Fun) Dog_Walk;
a_Dog->vtable.Dtor = (Animal_Vtable::Dtor_Fun) Dog_Dtor;
return a_Dog;
}
int main(int argc, char **argv){
/*
Base class:
Animal *a_Animal = Animal_New(Animal_Alloc());
*/
Animal *a_Animal = (Animal*)Dog_New(Dog_Alloc());
a_Animal->vtable.Walk(a_Animal);
Animal_Free(a_Animal);
}
PS. This is tested on a C++ compiler, but it should be easy to make it work on a C compiler.
Check out GObject. It's meant to be OO in C and one implementation of what you're looking for. If you really want OO though, go with C++ or some other OOP language. GObject can be really tough to work with at times if you're used to dealing with OO languages, but like anything, you'll get used to the conventions and flow.
This has been interesting to read. I have been pondering the same question myself, and the benefits of thinking about it are this:
Trying to imagine how to implement OOP concepts in a non-OOP language helps me understand the strengths of the OOp language (in my case, C++). This helps give me better judgement about whether to use C or C++ for a given type of application -- where the benefits of one out-weighs the other.
In my browsing the web for information and opinions on this I found an author who was writing code for an embedded processor and only had a C compiler available:
http://www.eetimes.com/discussion/other/4024626/Object-Oriented-C-Creating-Foundation-Classes-Part-1
In his case, analyzing and adapting OOP concepts in plain C was a valid pursuit. It appears he was open to sacrificing some OOP concepts due to the performance overhead hit resulting from attempting to implement them in C.
The lesson I've taken is, yes it can be done to a certain degree, and yes, there are some good reasons to attempt it.
In the end, the machine is twiddling stack pointer bits, making the program counter jump around and calculating memory access operations. From the efficiency standpoint, the fewer of these calculations done by your program, the better... but sometimes we have to pay this tax simply so we can organize our program in a way that makes it least susceptible to human error. The OOP language compiler strives to optimize both aspects. The programmer has to be much more careful implementing these concepts in a language like C.
There are several techniques that can be used. The most important one is more how to split the project. We use an interface in our project that is declared in a .h file and the implementation of the object in a .c file. The important part is that all modules that include the .h file see only an object as a void *, and the .c file is the only module who knows the internals of the structure.
Something like this for a class we name FOO as an example:
In the .h file
#ifndef FOO_H_
#define FOO_H_
...
typedef struct FOO_type FOO_type; /* That's all the rest of the program knows about FOO */
/* Declaration of accessors, functions */
FOO_type *FOO_new(void);
void FOO_free(FOO_type *this);
...
void FOO_dosomething(FOO_type *this, param ...):
char *FOO_getName(FOO_type *this, etc);
#endif
The C implementation file will be something like that.
#include <stdlib.h>
...
#include "FOO.h"
struct FOO_type {
whatever...
};
FOO_type *FOO_new(void)
{
FOO_type *this = calloc(1, sizeof (FOO_type));
...
FOO_dosomething(this, );
return this;
}
So I give the pointer explicitly to an object to every function of that module. A C++ compiler does it implicitly, and in C we write it explicitly out.
I really use this in my programs, to make sure that my program does not compile in C++, and it has the fine property of being in another color in my syntax highlighting editor.
The fields of the FOO_struct can be modified in one module and another module doesn't even need to be recompiled to be still usable.
With that style I already handle a big part of the advantages of OOP (data encapsulation). By using function pointers, it's even easy to implement something like inheritance, but honestly, it's really only rarely useful.
You may find it helpful to look at Apple's documentation for its Core Foundation set of APIs. It is a pure C API, but many of the types are bridged to Objective-C object equivalents.
You may also find it helpful to look at the design of Objective-C itself. It's a bit different from C++ in that the object system is defined in terms of C functions, e.g. objc_msg_send to call a method on an object. The compiler translates the square bracket syntax into those function calls, so you don't have to know it, but considering your question you may find it useful to learn how it works under the hood.
You can fake it using function pointers, and in fact, I think it is theoretically possible to compile C++ programs into C.
However, it rarely makes sense to force a paradigm on a language rather than to pick a language that uses a paradigm.
Object oriented C, can be done, I've seen that type of code in production in Korea, and it was the most horrible monster I'd seen in years (this was like last year(2007) that I saw the code).
So yes it can be done, and yes people have done it before, and still do it even in this day and age. But I'd recommend C++ or Objective-C, both are languages born from C, with the purpose of providing object orientation with different paradigms.
Yes, you can. People were writing object-oriented C before C++ or Objective-C came on the scene. Both C++ and Objective-C were, in parts, attempts to take some of the OO concepts used in C and formalize them as part of the language.
Here's a really simple program that shows how you can make something that looks-like/is a method call (there are better ways to do this. This is just proof the language supports the concepts):
#include<stdio.h>
struct foobarbaz{
int one;
int two;
int three;
int (*exampleMethod)(int, int);
};
int addTwoNumbers(int a, int b){
return a+b;
}
int main()
{
// Define the function pointer
int (*pointerToFunction)(int, int) = addTwoNumbers;
// Let's make sure we can call the pointer
int test = (*pointerToFunction)(12,12);
printf ("test: %u \n", test);
// Now, define an instance of our struct
// and add some default values.
struct foobarbaz fbb;
fbb.one = 1;
fbb.two = 2;
fbb.three = 3;
// Now add a "method"
fbb.exampleMethod = addTwoNumbers;
// Try calling the method
int test2 = fbb.exampleMethod(13,36);
printf ("test2: %u \n", test2);
printf("\nDone\n");
return 0;
}
If you are convinced that an OOP approach is superior for the problem you are trying to solve, why would you be trying to solve it with a non-OOP language? It seems like you're using the wrong tool for the job. Use C++ or some other object-oriented C variant language.
If you are asking because you are starting to code on an already existing large project written in C, then you shouldn't try to force your own (or anyone else's) OOP paradigms into the project's infrastructure. Follow the guidelines that are already present in the project. In general, clean APIs and isolated libraries and modules will go a long way towards having a clean OOP-ish design.
If, after all this, you really are set on doing OOP C, read this (PDF).
Of course, it just won't be as pretty as using a language with built-in support. I've even written "object-oriented assembler".
A little OOC code to add:
#include <stdio.h>
struct Node {
int somevar;
};
void print() {
printf("Hello from an object-oriented C method!");
};
struct Tree {
struct Node * NIL;
void (*FPprint)(void);
struct Node *root;
struct Node NIL_t;
} TreeA = {&TreeA.NIL_t,print};
int main()
{
struct Tree TreeB;
TreeB = TreeA;
TreeB.FPprint();
return 0;
}
I've been digging this for one year:
As the GObject system is hard to use with pure C, I tried to write some nice macros to ease the OO style with C.
#include "OOStd.h"
CLASS(Animal) {
char *name;
STATIC(Animal);
vFn talk;
};
static int Animal_load(Animal *THIS,void *name) {
THIS->name = name;
return 0;
}
ASM(Animal, Animal_load, NULL, NULL, NULL)
CLASS_EX(Cat,Animal) {
STATIC_EX(Cat, Animal);
};
static void Meow(Animal *THIS){
printf("Meow!My name is %s!\n", THIS->name);
}
static int Cat_loadSt(StAnimal *THIS, void *PARAM){
THIS->talk = (void *)Meow;
return 0;
}
ASM_EX(Cat,Animal, NULL, NULL, Cat_loadSt, NULL)
CLASS_EX(Dog,Animal){
STATIC_EX(Dog, Animal);
};
static void Woof(Animal *THIS){
printf("Woof!My name is %s!\n", THIS->name);
}
static int Dog_loadSt(StAnimal *THIS, void *PARAM) {
THIS->talk = (void *)Woof;
return 0;
}
ASM_EX(Dog, Animal, NULL, NULL, Dog_loadSt, NULL)
int main(){
Animal *animals[4000];
StAnimal *f;
int i = 0;
for (i=0; i<4000; i++)
{
if(i%2==0)
animals[i] = NEW(Dog,"Jack");
else
animals[i] = NEW(Cat,"Lily");
};
f = ST(animals[0]);
for(i=0; i<4000; ++i) {
f->talk(animals[i]);
}
for (i=0; i<4000; ++i) {
DELETE0(animals[i]);
}
return 0;
}
Here is my project site (I don't have enough time to write en. doc,however the doc in chinese is much better).
OOC-GCC
There is an example of inheritance using C in Jim Larson's 1996 talk given at the Section 312 Programming Lunchtime Seminar here: High and Low-Level C.
Which articles or books are good to use OOP concepts in C?
Dave Hanson's C Interfaces and Implementations is excellent on encapsulation and naming and very good on use of function pointers. Dave does not try to simulate inheritance.
OOP is only a paradigm which place datas as more important than code in programs. OOP is not a language. So, like plain C is a simple language, OOP in plain C is simple too.
One thing you might want to do is look into the implementation of the Xt toolkit for X Window. Sure it is getting long in the tooth, but many of the structures used were designed to work in an OO fashion within traditional C. Generally this means adding an extra layer of indirection here and there and designing structures to lay over each other.
You can really do lots in the way of OO situated in C this way, even though it feels like it some times, OO concepts did not spring fully formed from the mind of #include<favorite_OO_Guru.h>. They really constituted many of the established best practice of the time. OO languages and systems only distilled and amplified parts of the programing zeitgeist of the day.
The answer to the question is 'Yes, you can'.
Object-oriented C (OOC) kit is for those who want to program in an object-oriented manner, but sticks on the good old C as well. OOC implements classes, single and multiple inheritance, exception handling.
Features
• Uses only C macros and functions, no language extensions required! (ANSI-C)
• Easy-to-read source code for your application. Care was taken to make things as simple as possible.
• Single inheritance of classes
• Multiple inheritance by interfaces and mixins (since version 1.3)
• Implementing exceptions (in pure C!)
• Virtual functions for classes
• External tool for easy class implementation
For more details, visit http://ooc-coding.sourceforge.net/.
It's seem like people are trying emulate the C++ style using C. My take is that doing object-oriented programming C is really doing struct-oriented programming. However, you can achieve things like late binding, encapsulation, and inheritance. For inheritance you explicitly define a pointer to the base structs in your sub struct and this is obviously a form of multiple inheritance. You'll also need to determine if your
//private_class.h
struct private_class;
extern struct private_class * new_private_class();
extern int ret_a_value(struct private_class *, int a, int b);
extern void delete_private_class(struct private_class *);
void (*late_bind_function)(struct private_class *p);
//private_class.c
struct inherited_class_1;
struct inherited_class_2;
struct private_class {
int a;
int b;
struct inherited_class_1 *p1;
struct inherited_class_2 *p2;
};
struct inherited_class_1 * new_inherited_class_1();
struct inherited_class_2 * new_inherited_class_2();
struct private_class * new_private_class() {
struct private_class *p;
p = (struct private_class*) malloc(sizeof(struct private_class));
p->a = 0;
p->b = 0;
p->p1 = new_inherited_class_1();
p->p2 = new_inherited_class_2();
return p;
}
int ret_a_value(struct private_class *p, int a, int b) {
return p->a + p->b + a + b;
}
void delete_private_class(struct private_class *p) {
//release any resources
//call delete methods for inherited classes
free(p);
}
//main.c
struct private_class *p;
p = new_private_class();
late_bind_function = &implementation_function;
delete_private_class(p);
compile with c_compiler main.c inherited_class_1.obj inherited_class_2.obj private_class.obj.
So the advice is to stick to a pure C style and not try to force into a C++ style. Also this way lends itself to a very clean way of building an API.
See http://slkpg.byethost7.com/instance.html for yet another twist on OOP in C. It emphasizes instance data for reentrancy using just native C. Multiple inheritance is done manually using function wrappers. Type safety is maintained. Here is a small sample:
typedef struct _peeker
{
log_t *log;
symbols_t *sym;
scanner_t scan; // inherited instance
peek_t pk;
int trace;
void (*push) ( SELF *d, symbol_t *symbol );
short (*peek) ( SELF *d, int level );
short (*get) ( SELF *d );
int (*get_line_number) ( SELF *d );
} peeker_t, SlkToken;
#define push(self,a) (*self).push(self, a)
#define peek(self,a) (*self).peek(self, a)
#define get(self) (*self).get(self)
#define get_line_number(self) (*self).get_line_number(self)
INSTANCE_METHOD
int
(get_line_number) ( peeker_t *d )
{
return d->scan.line_number;
}
PUBLIC
void
InitializePeeker ( peeker_t *peeker,
int trace,
symbols_t *symbols,
log_t *log,
list_t *list )
{
InitializeScanner ( &peeker->scan, trace, symbols, log, list );
peeker->log = log;
peeker->sym = symbols;
peeker->pk.current = peeker->pk.buffer;
peeker->pk.count = 0;
peeker->trace = trace;
peeker->get_line_number = get_line_number;
peeker->push = push;
peeker->get = get;
peeker->peek = peek;
}
I'm a bit late to the party, but I want to share my experience on the topic: I work with embedded stuff these days, and the only (reliable) compiler I have is C, so that I want to apply object-oriented approach in my embedded projects written in C.
Most of the solutions I've seen so far use typecasts heavily, so we lose type safety: compiler won't help you if you make a mistake. This is completely unacceptable.
Requirements that I have:
Avoid typecasts as much as possible, so we don't lose type safety;
Polymorphism: we should be able to use virtual methods, and user of the class should not be aware whether some particular method is virtual or not;
Multiple inheritance: I don't use it often, but sometimes I really want some class to implement multiple interfaces (or to extend multiple superclasses).
I've explained my approach in detail in this article: Object-oriented programming in C; plus, there is an utility for autogeneration of boilerplate code for base and derived classes.
I built a little library where I tried that and to me it works real nicely. So I thought I share the experience.
https://github.com/thomasfuhringer/oxygen
Single inheritance can be implemented quite easily using a struct and extending it for every other child class. A simple cast to the parent structure makes it possible to use parent methods on all the descendants.
As long as you know that a variable points to a struct holding this kind of an object you can always cast to the root class and do introspection.
As has been mentioned, virtual methods are somewhat trickier. But they are doable. To keep things simple I just use an array of functions in the class description structure which every child class copies and repopulates individual slots where required.
Multiple inheritance would be rather complicated to implement and comes with a significant performance impact. So I leave it. I do consider it desirable and useful in quite a few cases to cleanly model real life circumstances, but in probably 90% of cases single inheritance covers the needs. And single inheritance is simple and costs nothing.
Also I do not care about type safety. I think you should not depend on the compiler to prevent you from programming mistakes. And it shields you only from a rather small part of errors anyway.
Typically, in an object oriented environment you also want to implement reference counting to automate memory management to the extent possible. So I also put a reference count into the “Object” root class and some functionality to encapsulate allocation and deallocation of heap memory.
It is all very simple and lean and gives me the essentials of OO without forcing me to deal with the monster that is C++. And I retain the flexibility of staying in C land, which among other things makes it easier to integrate third party libraries.
I propose to use Objective-C, which is a superset of C.
While Objective-C is 30 years old, it allows to write elegant code.
http://en.wikipedia.org/wiki/Objective-C
Yes, it is possible.
This is pure C, no macros preprocessing. It has inheritance, polymorphism, data encapsulation (including private data). It does not have equivalent protected qualifier, wich means private data is private down the inheritance chain too.
#include "triangle.h"
#include "rectangle.h"
#include "polygon.h"
#include <stdio.h>
int main()
{
Triangle tr1= CTriangle->new();
Rectangle rc1= CRectangle->new();
tr1->width= rc1->width= 3.2;
tr1->height= rc1->height= 4.1;
CPolygon->printArea((Polygon)tr1);
printf("\n");
CPolygon->printArea((Polygon)rc1);
}
/*output:
6.56
13.12
*/

OOP in C, implicitly pass self as parameter

I've been working on an example to learn OOP in C. Currently I've come up with this code which is working, however I'm interested in making the methods implicitly pass self as a parameter.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
//#include "Stopwatch.h"
typedef struct stopwatch_s
{
unsigned int milliseconds;
unsigned int seconds;
unsigned int minutes;
unsigned int hours;
bool is_enabled;
void ( *tick ) ( struct stopwatch_s* );
void ( *start ) ( struct stopwatch_s* );
void ( *stop ) ( struct stopwatch_s* );
void ( *reset ) ( struct stopwatch_s* );
} stopwatch_t;
static void tick (stopwatch_t* _self)
{
stopwatch_t * self = _self;
if (self->is_enabled)
{
self->milliseconds++;
if (self->milliseconds >= 1000)
{
self->milliseconds = 0;
self->seconds++;
if (self->seconds >= 60)
{
self->seconds = 0;
self->minutes++;
if (self->minutes >= 60)
{
self->minutes = 0;
self->hours++;
}
}
}
}
}
static void start (stopwatch_t* _self)
{
stopwatch_t * self = _self;
self->is_enabled = true;
}
static void stop (stopwatch_t* _self)
{
stopwatch_t * self = _self;
self->is_enabled = false;
}
static void reset (stopwatch_t* _self)
{
stopwatch_t * self = _self;
self->is_enabled = false;
self->milliseconds = 0;
self->seconds = 0;
self->minutes = 0;
self->hours = 0;
}
void * new_stopwatch()
{
stopwatch_t * newInstance = (stopwatch_t *)calloc(1, sizeof(stopwatch_t));
newInstance->is_enabled = false;
newInstance->milliseconds = 0;
newInstance->seconds = 0;
newInstance->minutes = 0;
newInstance->hours = 0;
newInstance->tick = &tick;
newInstance->start = &start;
newInstance->stop = &stop;
newInstance->reset = &reset;
return newInstance;
}
void main()
{
struct stopwatch_s * Stopwatch = new_stopwatch();
printf ("Initial: %d\n", Stopwatch->milliseconds);
Stopwatch->start (Stopwatch);
Stopwatch->tick (Stopwatch);
Stopwatch->tick (Stopwatch);
Stopwatch->tick (Stopwatch);
printf ("Started: %d\n", Stopwatch->milliseconds);
Stopwatch->stop (Stopwatch);
Stopwatch->tick (Stopwatch);
printf ("Stopped: %d\n", Stopwatch->milliseconds);
Stopwatch->reset (Stopwatch);
printf ("Reset: %d\n", Stopwatch->milliseconds);
}
I've tried reading and following Object Oriented Programming with ANSI-C, but can't wrap my head around how to structure my "object" so instead of
Stopwatch->tick(Stopwatch);
I can write
Stopwatch->tick();
I can't wrap my head around how to structure my "object" so instead of
Stopwatch->tick(Stopwatch);
I can write Stopwatch->tick();
This is not possible in standard C. You need to pass the receiver as an explicit formal argument to your C functions (in contrast with C++ which has this as an implicit formal).
However:
you generally want to pack all the method functions in one single struct with several function members (and have each instance start with a pointer to that struct). Read about vtable-s.
you could have some macro (or perhaps inline function) to avoid giving Stopwatch twice; you'll still write TICK(Stopwatch) not Stopwatch->tick();; the statement-expr extension of GCC could be useful.
Look into GTK and its Gobject system as an example of a cute object system for C. Read also about the ObjVLisp model and wikipage on virtual method tables. Maybe see this draft report and RefPerSys and also the blog of the late J.Pitrat.
BTW, you could decide that you have first class method selectors (perhaps as integers, or pointers to some common selector type) and code a variadic send dispatching function (so you would code send(StopWatch,TICK_SEL) instead of your dreamed Stopwatch->tick()) or macro. You might find libffi useful. The old Xview could be inspirational.
At last, as many fancy object layer implementors, you might use some metaprogramming and provide some C code generating tool (like moc in Qt). You might even consider customizing your GCC compiler with MELT for such purposes. Or making a translator (see this) from your fancy OOP dialect to C (like VALA or SWIG or Bigloo or Chicken-Scheme do; see also this). Or preprocess your code with an external preprocessor (your own one, or m4 or GPP, etc...).
Note: there are already a number of good answers, which explain why the "method call" syntax is not available in C, however they do not explain what to do instead but just point at resources. Basic OO in C is actually relatively simple, so here is a quick HOW TO.
This HOW TO is separated in two sections:
the first section shows how to achieve encapsulation
the second section shows how to layer late binding on top
Encapsulation
Often times, OO is actually used to mean encapsulation. The idea of encapsulation is to obtain a modular design with well defined interfaces over the state of the program in the hope of making it easier to maintain invariants.
In C, this is traditionally achieved through opaque pointers:
// stop_watch.h
typedef struct stop_swatch_ stop_watch;
stop_watch* stop_watch_create();
stop_watch* stop_watch_clone(stop_watch const* sw);
void stop_watch_dispose(stop_watch* sw);
void stop_watch_tick(stop_watch* sw);
void stop_watch_start(stop_watch* sw);
void stop_watch_stop(stop_watch* sw);
void stop_watch_reset(stop_watch* sw);
This header is the only thing the user sees, and therefore it cannot name the internals of the struct stop_watch_. Of course, this being C, the user can still mess with them, but at least we made it a bit harder on them.
Note: the .c is left as an exercise to the reader; it's plain boring C code after all.
Late Binding
Late Binding is deciding at run-time which function to call; it can for example be achieved through virtual methods in C++, Java, ...
It can be done in C, with relative ease, as well. You will just not benefit from all the sugar.
// stop_watch.h
typedef struct stop_watch_functions_ stop_watch_functions;
typedef struct {
stop_watch_functions const* functions;
} stop_watch;
struct stop_watch_functions_ {
void (*clone)(stop_watch const*);
void (*dispose)(stop_watch*);
void (*tick)(stop_watch*);
void (*start)(stop_watch*);
void (*stop)(stop_watch*);
void (*reset)(stop_watch*);
};
stop_watch* stop_watch_clone(stop_watch const* sw);
void stop_watch_dispose(stop_watch* sw);
void stop_watch_tick(stop_watch* sw);
void stop_watch_start(stop_watch* sw);
void stop_watch_stop(stop_watch* sw);
void stop_watch_reset(stop_watch* sw);
Alright, so we define:
a v-table: stop_watch_functions
a struct to hold onto that v-table: stop_watch; it is meant to be part of the instance of the concrete stop-watch.
Let's move on to the implementation:
// stop_watch.c
stop_watch* stop_watch_clone(stop_watch const* sw) {
return (*sw->functions->clone)(sw);
}
void stop_watch_dispose(stop_watch* sw) {
return (*sw->functions->dispose)(sw);
}
void stop_watch_tick(stop_watch* sw) {
return (*sw->functions->tick)(sw);
}
void stop_watch_start(stop_watch* sw) {
return (*sw->functions->start)(sw);
}
void stop_watch_stop(stop_watch* sw) {
return (*sw->functions->stop)(sw);
}
void stop_watch_reset(stop_watch* sw) {
return (*sw->functions->reset)(sw);
}
Pretty straightforward, right?
And finally, let's move on to a concrete stop-watch implementation:
// my_stop_watch.h
#include "stop_watch.h"
typedef struct my_stop_watch_ my_stop_watch;
my_stop_watch* my_stop_watch_create();
stop_watch* my_stop_watch_upcast(my_stop_watch* msw);
my_stop_watch* my_stop_watch_downcast(stop_watch* sw);
Okay, the header is boring; all the good stuff in hidden away after all:
// my_stop_watch.c
#include "my_stop_watch.h"
struct my_stop_watch_ {
stop_watch base;
unsigned int milliseconds;
unsigned int seconds;
unsigned int minutes;
unsigned int hours;
bool is_enabled;
};
static stop_watch* my_stop_watch_clone(stop_watch const* sw) {
my_stop_watch* new = malloc(sizeof(my_stop_watch));
memset(new, (my_stop_watch const*)sw, sizeof(my_stop_watch));
}
static void my_stop_watch_dispose(stop_watch* sw) {
free(sw);
}
static void my_stop_watch_tick(stop_watch* sw) {
my_stop_watch* msw = (my_stop_watch*)sw;
/* do something */
}
static void my_stop_watch_start(stop_watch* sw) {
my_stop_watch* msw = (my_stop_watch*)sw;
/* do something */
}
static void my_stop_watch_stop(stop_watch* sw) {
my_stop_watch* msw = (my_stop_watch*)sw;
/* do something */
}
static void my_stop_watch_reset(stop_watch* sw) {
my_stop_watch* msw = (my_stop_watch*)sw;
/* do something */
}
static stop_watch_functions const my_stop_watch_table = {
&my_stop_watch_clone,
&my_stop_watch_dispose,
&my_stop_watch_tick,
&my_stop_watch_start,
&my_stop_watch_stop,
&my_stop_watch_reset
};
my_stop_watch* my_stop_watch_create() {
my_stop_watch* msw = malloc(sizeof(my_stop_watch*));
msw->base = &my_stop_watch_table;
/* do something */
return msw;
}
stop_watch* my_stop_watch_upcast(my_stop_watch* msw) {
return &msw->base;
}
my_stop_watch* my_stop_watch_downcast(stop_watch* sw) {
if (sw->functions != &my_stop_watch_table) {
return NULL;
}
return (my_stop_watch*)((char*)sw - offsetof(my_stop_watch, base));
}
Here I used the strategy of most C++ implementations (with a virtual table); there are other strategies available, but this one is widely applicable.
Why I never liked that book much, is that tries to turn C into C++. Everyone must first realize that C++ programming is not necessarily the same as object-oriented programming. OOP is a way to do program design and it is quite unrelated to language syntax. C++ just makes it easier and prettier, is all. But just because C++ has a feature that makes code prettier in some situation, it doesn't necessarily mean that the feature is at all related to OOP (take for example operator overloading).
So don't try to turn C into C++. Accept that C has different syntax, which may not be as pretty. C actually has lots of functionality available that lets you implement OOP design. True encapsulation with private/public variables or functions is 100% achievable in C.
Since C is not C++, you don't want member functions inside the struct. The only function pointer you'll want there are special cases such as callback functions and similar. So instead of Stopwatch->tick(&Stopwatch), it is better not to use function pointers at all, but to call the member function directly: sw_tick(&Stopwatch). Where sw is some unique prefix for the stopwatch module.
This allows you to implement Stopwatch as an object of incomplete type (also called "opaque type"), which is the very core of OOP in C. Incomplete type allows you to hide the contents of the struct to the caller.
Then rewrite the whole stopwatch "class" (call it class or ADT or whatever) as something like this:
stopwatch.h
typedef struct stopwatch_t stopwatch_t; // incomplete type
stopwatch_t* sw_new (void); // "constructor"
void sw_delete (stopwatch_t* sw); // "destructor"
void sw_tick (const stopwatch_t* sw); // public member function
// any number of public functions here
// mind const correctness!
stopwatch.c
struct stopwatch_t // implementation
{
// true private variables:
unsigned int milliseconds;
unsigned int seconds;
unsigned int minutes;
unsigned int hours;
bool is_enabled;
};
stopwatch_t* sw_new (void)
{
// same as what you already have
}
// the module is responsible for cleaning up its own mess, NOT THE CALLER
void sw_delete (stopwatch_t* sw)
{
free(sw);
}
// any number of public member functions:
void sw_tick (const stopwatch_t* sw)
{
// here sw is the "self"/"this" pointer
}
// any number of private member functions:
static void sw_do_stuff (stopwatch_t* sw)
{
}
The caller will only be able to declare pointers to objects, but never an instance of them. That's no big deal, lots of C and C++ libraries work that way. A pointer to incomplete type is somewhat similar to a pointer to an abstract base class in C++. You can't declare instances of those either.
If you need to mix private and public member variables, you would typedef a struct in the h file where the public member variables are declared as plain struct members, and the private member variables are declared through an incomplete type.
That's simpy not a language feature of C, and that probably was one of the motivations to invent C++, so with C alone, this is impossible.
There's a lot of libraries in C, and basically all I know use the same approach as you, using structs to store states (in your case, stopwatch_t), but just skip the function pointers in the structs wherever possible; this is not because C programmers don't like OOP, but because it's less redundant to do e.g.
stoplib_tick(Stopwatch);
instead of
Stopwatch->tick(Stopwatch);
Also, it's a bad idea to carry around a bunch of function pointers in every instance of your struct that are always the same; it's just a waste of space, and a possible cause for error. If you want, you can make one struct that contains all the function pointers for your type, and call them from that table. Basically, that's what VTables in C++ are, underneath.
Hence, no C programmer would do this; unless your function pointer is actually something that might change, you just don't keep the operations you can do on a struct in that struct.
I don't know that book you're referring to, but if it preaches doing that, I don't like it.
Seriously, if you want C with object orientation, go for C++; aside from coding for a few kernels, there's very little you can't do with C++ that you can do with C, and it was really invented half an eternity ago to bring object orientation to C programmers. Don't be the 1960s.
EDIT started to read the PDF you link to -- seriously, who would use ANSI-C nowadays? Especially if you want to comfortably work with structs etc, you should not use anything older than C99 (considering that's pretty old already...), and hence, that book is hopelessly outdated, unless you come up with a system of huge importance and heritage ("hi, I'm working on nuclear weapon control systems from the 1980s and I need to fix this and that"), I'd say I can't think of a case where it would make sense following these examples; obviously, "I'm learning to do OOP in C from scratch" shouldn't be based on things that have been obsolete for more than a decade.
EDIT: you comment
As where I come from is an embedded environment, sticking to ANSI-C, things will always work.
I kind of reluctantly agree. C99 support is lacking on some platforms, but: most compilers support the vast majority of C99 features. ANSI-C (should more correctly be called C89, because C99 is also an ANSI standard) is really more than 25 years old now, and without knowing, your code might even not comply with C89. The code in the book sure as hell is not valid ANSI-C, no matter what the author claims. ANSI-C doesn't have // comments, for example; this is but a minor mistake, and I'd guess all compilers, unless set to pedantic mode wouldn't complain, but still, it's not a good sight.
So: do yourself a favor and don't rely on a book that's selectively using hard-to-use language statuses and try to use whatever your compiler supports.
Also: the more I read that book, the less a good excercise in (modern) OOP it seems to be (p. 3, on the PDF page 9):
The generic pointer void * is used throughout. On the one hand it makes it
impossible to discover what a set looks like, but on the other hand it permits us to
pass virtually anything to add() and the other functions.
Yes, because type safety isn't a concept vital to the success of C, and because it's a good idea to pass void* and then, first line of the method, cast it to your desired pointer type. Aargh! If you want terrible bugs, that's how you get them.
Look at things like CPython: Python is a OO language, yet the interpreter/compiler is written in C. Python does C-OOP with the PyObject struct, which, as a main feature, has a type reference, so to avoid doing these blind casts. You shouldn't be able to pass a const char[] where you're expecting a pointer to one of your objects, and the whole point of polymorphism is that you can use daughter types of your type, but not completely disparate types, with a function. The book really doesn't do OOP any good. Read something else. I'm pretty sure there's books on CPython's design, and I'd personally think that they can't be worse.

memcpy Inheritance-like structs - is it safe?

I have two structs I'm working with, and they are defined nearly identical. These are defined in header files that I cannot modify.
typedef struct
{
uint32_t property1;
uint32_t property2;
} CarV1;
typedef struct
{
uint32_t property1;
uint32_t property2;
/* V2 specific properties */
uint32_t property3;
uint32_t property4;
} CarV2;
In my code, I initialize the V2 struct at the top of my file, to cover all my bases:
static const carV2 my_car = {
.property1 = value,
.property2 = value,
/* V2 specific properties */
.property3 = value,
.property4 = value
};
Later, I want to retrieve the values I have initialized and copy them into the struct to be returned from a function via void pointer. I sometimes want V2 properties of the car, and sometimes V1. How can I memcpy safely without having duplicate definitions/initializations? I'm fairly new to C, and its my understanding that this is ugly and engineers to follow me in looking at this code will not approve. What's a clean way to do this?
int get_properties(void *returned_car){
int version = get_version();
switch (version){
case V1:
{
CarV1 *car = returned_car;
memcpy(car, &my_car, sizeof(CarV1)); // is this safe? What's a better way?
}
case V2:
{
CarV2 *car = returned_car;
memcpy(car, &my_car, sizeof(CarV2));
}
}
}
Yes, it's definitely possible to do what you're asking.
You can use a base struct member to implement inheritance, like this:
typedef struct
{
uint32_t property1;
uint32_t property2;
} CarV1;
typedef struct
{
CarV1 base;
/* V2 specific properties */
uint32_t property3;
uint32_t property4;
} CarV2;
In this case, you're eliminating the duplicate definitions. Of course, on a variable of type CarV2*, you can't reference the fields of the base directly - you'll have to do a small redirection, like this:
cv2p->base.property1 = 0;
To upcast to CarV1*, do this:
CarV1* cv1p = &(cv2p->base);
c1vp->property1 = 0;
You've written memcpy(&car, &my_car, sizeof(CarV1)). This looks like a mistake, because it's copying the data of the pointer variable (that is, the address of your struct, instead of the struct itself). Since car is already a pointer (CarV1*) and I'm assuming that so is my_car, you probably wanted to do this instead:
memcpy(car, my_car, sizeof(CarV1));
If my_car is CarV2* and car is CarV1* (or vice versa), then the above code is guaranteed to work by the C standard, because the first member of a struct is always at a zero offset and, therefore, the memory layout of those two for the first sizeof(CarV1) bytes will be identical.
The compiler is not allowed to align/pad that part differently (which I assume is what you meant about optimizing), because you've explicitly declared the first part of CarV2 to be a CarV1.
Since in your case you are stuck with identically defined structs that you can't change, you may find useful that the C standard defines a macro/special form called offsetof.
To be absolutely sure about your memory layouts, I'd advise that you put a series of checks during the initialization phase of your program that verifies whether the offsetof(struct CarV1, property1) is equal to offsetof(struct CarV2, property1) etc for all common properties:
void validateAlignment(void)
{
if (offsetof(CarV1, property1) != offsetof(CarV2, property1)) exit(-1);
if (offsetof(CarV1, property2) != offsetof(CarV2, property2)) exit(-1);
// and so on
}
This will stop the program for going ahead in case the compiler has done anything creative with the padding.
It also won't slow down your program's initialization because offsetof is actually calculated at compile time. So, with all the optimizations in place, the void validateAlignment(void) function should be optimized out completely (because a static analysis would show that the exit conditions are always false).
What you wrote will almost work, except that instead of memcpy(&car, ... you should just have memcpy (car, ..., but there is no reason to use memcpy in such a case. Rather, you should just copy each of the fields in a separate statement.
car->property1 = my_car.property1
(is my_car a pointer or not? it's impossible to tell from the code fragment)
For the second case, I think you can just assign the entire struct: *car = my_car
there is no perfect solution but one way is to use a union
typedef union car_union
{
CarV1 v1;
CarV2 v2;
} Car;
that way the size will not differ when you do a memcpy - if version v1 then v2 specific parts will not be initialized.
In C and Objective-C, this is fine in practice. (In theory, the compiler must see the declaration of a union containing both structs as members).
In C++ (and Objective-C++), the language very carefully describes when this is safe and when it isn't. For example, if you start with
typedef struct {
public:
...
then the compiler is free to re-arrange where struct members are. If the struct uses no C++ features then you are safe.

C as an object oriented language

Could you suggest a syntax for the C language to use it in a similar way than an object-oriented language? I know that they cannot be the same and that some keywords aren't present in C, but I'm wondering if there is a way to take advantage of certain aspects (like inheritance) even in a C program.
You can implement polymorphism with regular functions and virtual tables (vtables). Here's a pretty neat system that I invented (based on C++) for a programming exercise:
(source: goblin.tkk.fi)
The constructors allocate memory and then call the class' init function where the memory is initialized. Each init function should also contain a static vtable struct that contains the virtual function pointers (NULL for pure virtual). Derived class init functions call the superclass init function before doing anything else.
A very nice API can be created by implementing the virtual function wrappers (not to be confused with the functions pointed to by the vtables) as follows (add static inline in front of it, if you do this in the header):
int playerGuess(Player* this) { return this->vtable->guess(this); }
Single inheritance can be done by abusing the binary layout of a struct:
(source: goblin.tkk.fi)
Notice that multiple inheritance is messier as then you often need to adjust the pointer value when casting between types of the hierarchy.
Other type-specific data can be added to the virtual tables as well. Examples include runtime type info (e.g. type name as a string), linking to superclass vtable and the destructor chain. You probably want virtual destructors where derived class destructor demotes the object to its super class and then recursively calls the destructor of that and so on, until the base class destructor is reached and that finally frees the struct.
There is the GObject library:
The GLib Object System, or GObject, is a free software library (covered by the LGPL) that provides a portable object system and transparent cross-language interoperability. GObject is designed for use both directly in C programs and through bindings to other languages.
The traditional solution is the function pointer struct. I emphasize traditional. I can tell you what sort of code I wrote in PL/I and C years ago, but I don't claim to speak for the state of the 'art' if you can call this art.
There are many variations on this, and the below is a bit of a compromise.
struct SortOfAnAbstractClass {
int (*function1)(SortOfAnAbstractClass* this, int arg1, int arg2, char * arg3);
void (*function2)(SortOfAnAbstractClass* this, char *arg);
};
struct SortOfDerived {
struct SortOfAnAbstractClass base;
int instanceVariable1;
};
SortOfAnAbstractClass getMeOne() {
SortOfDerived *d = malloc(sizeof SortOfDerived);
memset(d, 0, sizeof SortOfDerived);
d->function1 = myf1;
d->function2 = myf2;
return &d->base;
};
and then 'myf1' and 'myf2' cast their 'this' parameters and go to town. You can extend this to look ever more like a full virtual dispatch.
Another common variation from the mists of time:
struct SortOfAClass {
void *creatorInfo;
int (*function1)(SortOfAnAbstractClass* this, int arg1, int arg2, char * arg3);
void (*function2)(SortOfAnAbstractClass* this, char *arg);
};
In this variation, there's no inheritance by inclusion. The derived classes each put their private state into their own object in creatorInfo.
Take a look at the GObject library: http://library.gnome.org/devel/gobject/2.22/.
There are many variations to doing OO programming in C. The way I prefer to do it is to define one class per a header file. You'll notice a constructor new_testclass() which just initializes your function pointers and returns a pointer to an allocated class/struct. Also any function takes pointer to the class in the first parameter (something c++ does, but conceals).
testclass.h
#ifndef MALLOC_H
#include<malloc.h>
#endif
struct _testclass
{
int a;
int b;
int (*sum)(struct _testclass *obj);
};
typedef struct _testclass testclass;
int f_sum (testclass *obj)
{
return obj->a + obj->b;
}
testclass* new_testclass()
{
testclass *temp;
temp = (testclass*)malloc(sizeof(testclass));
temp->sum = &f_sum;
return temp;
}
Then you can simply use it.
testclass.c
#include <stdio.h>
#include "testclass.h"
int _tmain(int argc, _TCHAR* argv[])
{
int result;
testclass *testclass1;
testclass1 = new_testclass();
testclass1->a = 5;
testclass1->b = 8;
result = testclass1->sum(testclass1);
printf("%d\n",result);
free(testclass1);
return 0;
}
Of course there are several important aspects of object oriented programming missing here, but this provides a simple method for basic abstraction. I'd imagine inheritance would require some kind of funky preprocessor trick if it could be done at all.

Resources