[C] Inheritance, polymorphism and General coolness.

Talk about any languages right here. Share and discuss source, but don't expect your homework to be done for you.
Post Reply
mfukar
Apprentice
Posts: 36
Joined: Thu Sep 17, 2009 7:41 pm
Location: Athens, GR

[C] Inheritance, polymorphism and General coolness.

Post by mfukar » Mon Mar 01, 2010 3:18 am

Imagine an imaginary (well, duh!) device driver.

This driver is defined in a particular way, as dictated by your employer, Clunky McHackpherson. He says the driver must be defined in the following way:

Code: Select all

struct mydriver {
  struct driver_API d_api;
  struct character_driver char_dev;
  time_t timeout;
  int fd;
};
where struct members timeout and fd are driver-specific. Your driver adheres to some generic driver API, and as such inherits struct driver_API from it. It contains a bunch of useful as well as useless bloated functions, but more importantly:

Code: Select all

struct driver_API {
  /* 
   * PCI timeout update
   * Nobody knows exactly what this does.
   */
  time_t (*update_pci_timeout)(struct driver_API *d_api,
                               time_t new_timeout);
  /* more llama breeder functions */
};
However, you wish to overload this function with one that would make use of the timeout field, and generally do something that justifies your lowly salary. So you go ahead and rapid prototype a function that looks like this:

Code: Select all

time_t mydriver_update_pci_timeout(struct driver_API *d_api,
                                   time_t new_timeout)
{
  struct mydriver *mydriver_data;
  /* magic */
  mydriver_data = get_mydriver_ref(d_api);
  if ((mydriver_data->timeout) < 1942){
    do_small_timeout_stuff();
  }
  timeout_register(mydriver_data->timeout);
}
Huh? What is this magical get_mydriver_ref() ? It seems to return a pointer to our driver (struct mydriver) given a pointer to the inner struct driver_API!

Of course, this should only work if struct driver_API was previously instantiated as a member of a struct mydriver. Given our initial specifications, it is reasonable to assume so.

But, to the point. What does get_mydriver_ref() look like? This is a typical implementation:

Code: Select all

#define container_of(ptr, type, member) ({ \
  const typeof( ((type *)0)->member ) *__mptr = (ptr); \
  (type *)( (char *)__mptr - offsetof(type,member) );})

struct mydriver *get_mydriver_ref(struct driver_API *api){
  return container_of(api, struct mydriver, d_api);
}
Now, here's the great part. container_of is a macro defined in <linux/kernel.h>, in the Linux kernel sources. For another example of its usage, see inode.c inside the proc filesystem implementation (it is used to return procfs-specific data for a given inode). container_of uses the typeof macro, which is a GCC extension to refer to the type of an expression, and it can be used in the following trivial way:

Code: Select all

typeof (*x) y; /* Declare y with the type of what x points to. */
As well as more cryptic voodoo shenanigans.

A simpler approach to the same issue is to use the fact that the C language guarantees that, when a struct is the first member of another struct, they will both reside in the same base address. Therefore, a simple typecast is enough to achieve polymorphism. GTK+ and GLib use this approach. It is, however, limited to single inheritance. :evil:

The "container_of" case allows for traversal of an inheritance hierarchy when even multiple inheritance exists, but the traversing code must be aware of the structure of the hierarchy in order to reach a "higher" node. At each hierarchy level the traversing code must re-evaluate the address of the enclosing struct (exercise for the reader: why?).

I hope this will satisfy your curiosity, if nothing more. :mrgreen:

User avatar
IceDane
Because I Can
Posts: 2652
Joined: Wed May 12, 2004 9:25 am

Re: [C] Inheritance, polymorphism and General coolness.

Post by IceDane » Mon Mar 01, 2010 4:37 am

Awesome post, man.

Right now our standards are pretty low seeing as we almost only get spam, but compared to any standard this post is excellent. Feel free to post more of stuff like this.

Is epiphany work related? Are you writing device drivers at work?

mfukar
Apprentice
Posts: 36
Joined: Thu Sep 17, 2009 7:41 pm
Location: Athens, GR

Re: [C] Inheritance, polymorphism and General coolness.

Post by mfukar » Mon Mar 01, 2010 7:38 pm

I'm dealing with device drivers and the Linux kernel at work on a regular basis..writing, debugging, hacking.. Not many of them are written in this way, and object oriented implementations in C are a rare sight (besides a total pain), but I recently started this little Python project which would get me to learn about OOP in Python and I thought, hey, why don't I brush up on those neat OO tricks in C? I might post some more later on, if I get the chance. I might also post something about that Python project, it's really interesting to a Python newbie like me!

xtsop
n00b
Posts: 1
Joined: Wed Aug 07, 2013 11:05 am

Re: [C] Inheritance, polymorphism and General coolness.

Post by xtsop » Wed Aug 07, 2013 11:10 am

I would say that it is not polite to use material without citing it. This article is based on the link below:

http://modal-echoes.blogspot.co.uk/2007 ... -in-c.html

It's a matter of following an honor code since it is not an official publication but a blog post...

Cheers

Post Reply