Last active
August 18, 2017 16:17
-
-
Save cwshu/23b8e6401122279f7eaa556956ca257d to your computer and use it in GitHub Desktop.
container_of, interface inheritance
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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