Object Oriented C: Single inheritance Part II

Here’s another installment on Object Oriented C programming. This time, we’re going to take a look at how inheritance allows you to simulate a generic function courtesy of the C preprocessor. If you have ever wondered how those spiffy objects in other programming languages always get “printed,” here’s one way to do it.

First, let’s write a little code:

#include < stdio .h>

typedef struct _object Object;

#ifndef OOCP_PRINTFUNC
typedef int  (*PrintFunc) (void * stream,
                           const char * format,
                           ...); 
#define OOCP_PRINTFUNC
#endif 

#ifndef OOCP_PRINTER 
typedef void (*Printer)   (Object * o,
                           PrintFunc print_func,
                           void * stream);
#define OOCP_PRINTER
#endif

#define object_print(o,p,s)   ((Object*)o)->print ((Object*)o,(PrintFunc)p,s);

struct _object {
  Printer print;
};

typedef struct _thing {
  Object o;
  int value;
} Thing;

void
thing_printer(Object * o, PrintFunc print, void * stream) {

  Thing * t = (Thing *)o;
  print(stream, "Value from thing_printer: %dn", t->value);
}

int
main(int atgc, char ** argv) {

  Thing t;
  t.o.print = thing_printer;
  t.value = 1;

  object_print(&t, fprintf, stdout);

  return 0;
}

Ok, some 50 lines of code. Doesn’t look like much, but if you’re new to C, and haven’t been following along, rest assured: we’re starting to flex some muscle now.

That is, there’s a lot going on in this code.

Let’s start at the top:

typedef struct _object Object;

#ifndef OOCP_PRINTFUNC
typedef int  (*PrintFunc) (void * stream,
                           const char * format,
                           ...); 
#define OOCP_PRINTFUNC
#endif 
  • Line 3 is familiar, but we would normally expect this in a header file rather than a source file. We’re keeping the typedef here to keep the listing simple.
  • But what’s this typedef on Line 6? And why these ugly #defines on lines 5, 9 and 10?

Easy stuff first. The #defines protect your code from a compiler redefinition error. The idea is you want to define something in one place only, and have that thing (whatever it is) defined throughout your program. Remember, we’re dealing with strong typing, and a compiled language. Interpreted languages, Ruby or PHP for example, have little limitation on how your data may be defined.

In those languages, if you want to declare something a function in one line of code, then that same thing as an array in another line of code, that’s your business.

But not with C.

Line 6 gets into the meat. Recall we typedef’ed structs in header files to create hidden implementations. The type checker just needs the declaration to compile properly, the implementation can be anywhere within the typedef’s scope. Here, we’re using typedef to create a pointer to type of function, which is called PrintFunc.

If you think the prototype looks familiar, perhap similar to functions defined in stdio.h, you’re thinking correctly.

Let’s continue…

#ifndef OOCP_PRINTER 
typedef void (*Printer)   (Object * o,
                           PrintFunc print_func,
                           void * stream);
#define OOCP_PRINTER
#endif

#define object_print(o,p,s)   ((Object*)o)->print ((Object*)o,(PrintFunc)p,s);

struct _object {
  Printer print;
};

With Line 13, we’re getting a bit more esoteric. Now we’re building our typedef’ed function from our own derived types instead of C’s primitives, or from types defined in the standard library. We’ve seen this stuff before, though, even if just a few lines before in the case of PrintFunc.

Now, any function which prints and takes the same arguments as Printer can be assigned to a Printer variable. More importantly, such functions can be assigned to member variables in any struct declaring a Printer member.

But line 19 is whackadoodle.

It’s a macro. Not a function.

Recall in Java you have Object.tostring? This is pretty close to that.

We now have all the tools we need, so let’s put it together.

typedef struct _thing {
  Object o;
  int value;
} Thing;

void
thing_printer(Object * o, PrintFunc print, void * stream) {

  Thing * t = (Thing *)o;
  print(stream, "Value from thing_printer: %dn", t->value);
}

We’ve got our Thing (Line 25), and a way to print (Line 31) our Thing. Life is good.

Now let’s use our Thing:

int
main(int atgc, char ** argv) {

  Thing t;
  t.o.print = thing_printer;
  t.value = 1;

  object_print(&t, fprintf, stdout);

  return 0;
}

And there you have it, on Line 44: print that Thing out using it’s very own print “method.”

Exercise: Instead of declaring a Thing t, declare a Thing * t. Allocate its memory, print it, then remember to deallocate the memory afterwards. Run the program through valgrind to check your memory usage. You should have some memory left on the heap at the end of runtime, but nothing left over (no leaks).

The usual caveats…

You won’t want to use object_print for everything, but you might find that that a printing function defined in the same way works in a deeper class hierarchy. Suppose you have a Matrix class, which is the child of Object, and has children representing different kinds of matrices. In this case, having a matrix_print might be just the ticket.

Remember: object oriented anything is not a silver bullet for slaying design dragons. The simple framework we’re developing here is just that, simple. Instead of trying to bend your problem into this framework, use these concepts to create a framework that works best for your project.

Here’s some related material on function pointers:

  • The Function Pointer Tutorials: An excellent followup by Lars Haendel going into considerably more detail than what’s written here.
  • Declaring, Assigning, and Using Function Pointers: This is a classic piece of exposition on C, written by Steve Summit. I recall Steve from way back in Usenet days, before the World Wide Web. He’s the real deal and it’s worth studying this article in detail.

Stay tuned for an article specifically on how to typedef function pointers.

Single Inheritance In C Programming Language I: Nesting structures

The C programming language lends itself well to single inheritance object-oriented schemes, provided a little care is taken in the class structure.

Consider the following definition:

typedef struct _object {
  int foo;
} Object;

typedef struct _thing {
   Object o;
   double bar;
} Thing;

Right here, I know the double declaration has lost half of you, and lost all the systems programmers… but bear with me. My background is in scientific computation, doubles are our bread and butter.

What is this “Object” at the at the head of “_thing”?

Well, Object is the parent of Thing. Object blocks out a contiguous chunk of memory at the head of the _thing struct. This let’s you do the following:

  1. Cast to Object and access the members of Object.
  2. Pass any child of Object through a function definition as an Object type.

What’s it look like?

Casting to parent in function call

Let’s write a little program, using the two structures above:

void
print_foo(Object * o) {

  printf("o->foo: %dn", o->foo);
}

int
main (int argc, char ** argv) {

  Thing t;
  t.o.foo = 1;
  printf("t.o.foo: %dn", t.o.foo);
  print_foo(&t.o);
  print_foo((Object *)&t);
  return 0;
}

Assuming this little program is called “simple_inheritance.c,” compile with

gcc -DHAVE_CONFIG_H -I. -I..  -I../include -Wall -pedantic   -g -O2 -MT simple_inheritance.o -MD -MP -MF .deps/simple_inheritance.Tpo -c -o simple_inheritance.o simple_inheritance.c

Running simple_inheritance produces

$ ./simple_inheritance 
t.o.foo: 1
o->foo: 1
o->foo: 1
$

Spiffy, no?

Ok, this is semi-cool, but that obnoxious cast on line 14 spoils some of the fun.

As it turns out, that cast is necessary to keep the compiler from squawking about potential type errors, but… and this is a very important but… our handy C Preprocessor (CPP) can make that sort of go away. That is, we can write a macro to hide that cast, then invoke the macro when we to use foo.

Now if you’re like me, you’re gonna be thinking something like “Who gives a rat’s patootie about foo? Why is that useful to me?”

Remember those typedefs, how we hid the implementation of structures?

We can do the same thing with functions by typedef’ing callbacks, then using those callbacks as elements in our spiffy Object struct. Recall prissy languages like Java usually have some sort of to_string() method sitting way back up the inheritance tree, usually at it’s root, not surprisingly, called “Object.”

By now you should correctly surmise this little series of articles on Object Oriented C is going somewhere. I won’t claim to know where it’s going (and wouldn’t say if I knew), but it’s on its way somewhere.

In fact, these articles are writing themselves, so let’s just follow along and see where we end up.

Taxon, Taxa, Taxonomies. Ruh roh.

I do a bit of blogging here and there. One of the more recent, and more interesting, features of WordPress is its capability for defining custom taxonomies. A taxonomy, of course, being a collection of like items called taxa (sing. taxon), arranged in some sensible order.

However, trouble is brewing in paradise…

Taxonomy from Wikipedia:

Taxonomy is the practice and science of classification. The word finds its roots in the Greek ?????, taxis (meaning ‘order’ or ‘arrangement’) and ?????, nomos (meaning ‘law’ or ‘science’). Taxonomy uses taxonomic units, known as taxa (singular taxon).

So, what?

So, watch for this:

  • “taxonomy” will be used synonymously for taxon
  • “taxonomies” will be in lieu of taxa as the plural form

What this means is that when someone says “taxonomy” you are going to have to infer its meaning as an element in a collection of like elements collectively referred to as a taxonomy, or as the collection itself.

Frankly, stupid, pedantic words like “taxon” and “taxa” exist for a reason. Using the correct form of such words eliminates confusion.

Unfortunately, this requires people learning what such words actually mean. Which means either 1. reading, or 2. being instructed.

Which flies in the face of how the vast majority learn anything, which is to copy the accepted usage from peers, and not bother with the difficult details of real meaning.

Consequently, within WordPress, “taxonomy” is going to remain a slippery, confusing topic. If you don’t understand taxonomies, rest assured, that’s not entirely your fault.