aboutsummaryrefslogtreecommitdiff
path: root/examples/oop_example.c
diff options
context:
space:
mode:
authorDeterminant <[email protected]>2015-05-25 16:55:58 +0800
committerDeterminant <[email protected]>2015-05-25 16:55:58 +0800
commitbc1e2c57b1f234d153254845d62994bcd1a6e42f (patch)
treeb1f371eb3ebe97355d217288665a8fa15495cbfa /examples/oop_example.c
parent7dadb31a364c3dbe30c05c9a9040c48f1d4a9095 (diff)
rewrite the oop example
Diffstat (limited to 'examples/oop_example.c')
-rw-r--r--examples/oop_example.c135
1 files changed, 87 insertions, 48 deletions
diff --git a/examples/oop_example.c b/examples/oop_example.c
index 89f5994..859bd03 100644
--- a/examples/oop_example.c
+++ b/examples/oop_example.c
@@ -3,16 +3,18 @@
#include <stdlib.h>
#include "../common.h"
+#define SQR(x) ((x) * (x))
+
const char *point_tname = "nerv.Point";
+const char *better_point_tname = "nerv.BetterPoint";
typedef struct {
double x, y;
- int arr[100];
} Point;
-static int point_get_sinx (lua_State *L) {
+static int point_norm (lua_State *L) {
Point *p = luaT_checkudata(L, 1, point_tname);
- lua_pushnumber(L, sin(p->x));
+ lua_pushnumber(L, sqrt(SQR(p->x) + SQR(p->y)));
return 1;
}
@@ -22,67 +24,104 @@ static int point_set_x (lua_State *L) {
return 0;
}
-
-static int point_get_y(lua_State *L) {
+static int point_set_y (lua_State *L) {
Point *p = luaT_checkudata(L, 1, point_tname);
- lua_pushnumber(L, sin(p->x));
- return 1;
+ p->y = luaL_checknumber(L, 2);
+ return 0;
}
-static int point_newindex(lua_State *L) {
- Point *p = luaT_checkudata(L, 1, point_tname);
- if (lua_isnumber(L, 2))
- {
- int d = luaL_checkinteger(L, 2);
- double v = luaL_checknumber(L, 3);
- if (0 <= d && d < 100)
- p->arr[d] = v;
- lua_pushboolean(L, 1);
- return 1;
- }
- else
- {
- lua_pushboolean(L, 0);
- return 1;
- }
+/* generic constructor */
+void point_new_(Point *self, double x, double y) {
+ self->x = x;
+ self->y = y;
}
-static int point_index(lua_State *L) {
- Point *p = luaT_checkudata(L, 1, point_tname);
- if (lua_isnumber(L, 2))
- {
- int d = luaL_checkinteger(L, 2);
- if (0 <= d && d < 100)
- lua_pushnumber(L, p->arr[d]);
- lua_pushboolean(L, 1);
- return 2;
- }
- else
- {
- lua_pushboolean(L, 0);
- return 1;
- }
+int point_new(lua_State *L) {
+ /* `_new` function should create the object itself */
+ Point *self = (Point *)malloc(sizeof(Point));
+ point_new_(self, luaL_checknumber(L, 1), luaL_checknumber(L, 2));
+ luaT_pushudata(L, self, point_tname);
+ fprintf(stderr, "[example] %s constructor is invoked\n",
+ point_tname);
+ return 1;
}
-int point_new(lua_State *L) {
+int point___init(lua_State *L) {
+ /* The difference between this function and `_new` function is that this
+ * one is called by subclass of Point implemented in Lua, although it
+ * basically does the same thing as `_new`. Also, it can read the empty
+ * object (table) from the stack. (In this example, the table is ignored.) */
Point *self = (Point *)malloc(sizeof(Point));
- self->x = 0;
- self->y = 0;
+ point_new_(self, luaL_checknumber(L, 2), luaL_checknumber(L, 3));
luaT_pushudata(L, self, point_tname);
+ fprintf(stderr, "[example] A subclass has invoked `__init`\n");
return 1;
}
-static const luaL_Reg point[] = {
- {"get_sinx", point_get_sinx},
+static const luaL_Reg point_methods[] = {
{"set_x", point_set_x},
- {"get_y", point_get_y},
- {"__index__", point_index},
- {"__newindex__", point_newindex},
+ {"set_y", point_set_y},
+ {"__init", point___init},
+ {"norm", point_norm},
+ {NULL, NULL}
+};
+
+
+/* the subclass method overrides the one from baseclass */
+static int better_point_norm (lua_State *L) {
+ Point *p = luaT_checkudata(L, 1, point_tname);
+ lua_pushnumber(L, fabs(p->x) + fabs(p->y));
+ return 1;
+}
+
+int better_point_new(lua_State *L) {
+ /* `_new` function should create the object itself */
+ Point *self = (Point *)malloc(sizeof(Point));
+ point_new_(self, luaL_checknumber(L, 1), luaL_checknumber(L, 2));
+ luaT_pushudata(L, self, better_point_tname);
+ fprintf(stderr, "[example] %s constructor is invoked\n",
+ better_point_tname);
+ return 1;
+}
+
+int better_point___init(lua_State *L) {
+ /* The difference between this function and `_new` function is that this
+ * one is called by subclass of Point implemented in Lua, although it
+ * basically does the same thing as `_new`. Also, it can read the empty
+ * object (table) from the stack. (In this example, the table is ignored.) */
+ Point *self = (Point *)malloc(sizeof(Point));
+ point_new_(self, luaL_checknumber(L, 2), luaL_checknumber(L, 3));
+ luaT_pushudata(L, self, better_point_tname);
+ fprintf(stderr, "[example] A subclass has invoked `__init`\n");
+ return 1;
+}
+
+static const luaL_Reg better_point_methods[] = {
+ {"norm", better_point_norm},
+ {"__init", better_point___init},
{NULL, NULL}
};
void nerv_point_init(lua_State *L) {
- luaT_newmetatable(L, "nerv.Point", NULL, point_new, NULL, NULL);
- luaL_register(L, NULL, point);
+ /* create a class and let luaT know */
+ luaT_newmetatable(L, point_tname, NULL, point_new, NULL, NULL);
+ /* register member functions */
+ luaL_register(L, NULL, point_methods);
+ /* keep the stack balanced, see `nerv.c` */
+ lua_pop(L, 1);
+}
+
+void nerv_better_point_init(lua_State *L) {
+ /* create a class and let luaT know */
+ luaT_newmetatable(L, better_point_tname, point_tname,
+ better_point_new, NULL, NULL);
+ /* register member functions */
+ luaL_register(L, NULL, better_point_methods);
+ /* keep the stack balanced, see `nerv.c` */
lua_pop(L, 1);
}
+
+void nerv_example_init(lua_State *L) {
+ nerv_point_init(L);
+ nerv_better_point_init(L);
+}