Skip to content

Instantly share code, notes, and snippets.

@cwshu
Last active August 18, 2017 16:17
Show Gist options
  • Save cwshu/23b8e6401122279f7eaa556956ca257d to your computer and use it in GitHub Desktop.
Save cwshu/23b8e6401122279f7eaa556956ca257d to your computer and use it in GitHub Desktop.
container_of, interface inheritance
#include <stdio.h>
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
struct Adder {
int (*add)(struct Adder* self, int x, int y);
};
// struct Adder1 implement Adder
struct Adder1 {
struct Adder a;
};
int adder1_add(struct Adder* self, int x, int y){
struct Adder1* a1;
a1 = container_of(self, struct Adder1, a);
/*
* we can use anything in Adder1 by a1 to implement add() function
*/
return x+y;
}
struct Adder adder1_adder = {
.add = adder1_add,
};
int compute(struct Adder* a, int x, int y, int z){
int ret;
ret = a->add(a, x, y);
ret = a->add(a, ret, z);
return ret;
}
int main(int argc, char *argv[]){
struct Adder1 a1 = {.a = adder1_adder};
int x = compute(&a1.a, 1, 2, 3);
printf("x = %d\n", x);
return 0;
}
#include <stdio.h>
#include <string.h>
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
// interface Length
struct Length {
int (*len)(struct Length* l);
};
// class Int implement Length
struct Int {
struct Length length;
int value;
};
int int_len(struct Length* l){
struct Int* i = container_of(l, struct Int, length);
return i->value;
}
struct Length int_length = {
.len = int_len,
};
// class Double implement Length
struct Double {
struct Length length;
double value;
};
int double_len(struct Length* l){
struct Double* d = container_of(l, struct Double, length);
return (int)d->value;
}
struct Length double_length = {
.len = double_len,
};
// class String implement Length
struct String {
struct Length length;
char value[1024];
int size;
};
int string_len(struct Length* l){
struct String* s = container_of(l, struct String, length);
return s->size;
}
struct Length string_length = {
.len = string_len,
};
// polymorphic function
int sum(struct Length* l1, struct Length* l2){
return l1->len(l1) + l2->len(l2);
}
int main(int argc, char *argv[]){
struct Int i1 = {.length = int_length, .value = 5};
struct Int i2 = {.length = int_length, .value = 10};
struct Int i3 = {.length = int_length, .value = 15};
struct Double d1 = {.length = double_length, .value = 1.05};
struct Double d2 = {.length = double_length, .value = 1.10};
struct Double d3 = {.length = double_length, .value = 1.15};
struct String s1 = {.length = string_length};
struct String s2 = {.length = string_length};
struct String s3 = {.length = string_length};
strncpy(s1.value, "123", 3); s1.size = 3;
strncpy(s2.value, "hello", 5); s2.size = 5;
strncpy(s3.value, "<(_ _)>", 7); s3.size = 7;
printf("%d\n", sum(&i1.length, &i2.length));
printf("%d\n", sum(&i1.length, &d1.length));
printf("%d\n", sum(&i1.length, &s1.length));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment