comparison lua/luadyncall/src/smartptr.c @ 0:0cfcc391201f

initial from svn dyncall-1745
author Daniel Adler
date Thu, 19 Mar 2015 22:26:28 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:0cfcc391201f
1 /* lua smart pointers - version 0.2 (C only version) */
2 /* (C) 2010 Daniel Adler */
3
4 #include "lua.h"
5 #include "lauxlib.h"
6
7 #define LUA_SMARTPTR_LIBNAME "smartptr"
8 #define LUA_SMARTPTR_TNAME "SmartPtr"
9
10 /*
11 ** lua smart pointer
12 **
13 ** DESCRIPTION
14 ** the smart pointer wraps lightuserdata (lua's object type for carrying raw pointer values)
15 ** into a userdata structure where it also references a finalizer function, which will be called
16 ** with the lightuserdata (not the userdata!) as an argument.
17 **
18 **
19 ** LUA INTERFACE
20 ** smartptr = newsmartptr(lightuserdata, function)
21 ** setfinalizer(smartptr, function)
22 ** lightuserdata = tolightuserdata(integer)
23 **
24 */
25
26 typedef struct
27 {
28 const void* pointer;
29 int finalizer; /* lua reference */
30 } lua_SmartPtr;
31
32 /*
33 ** constructs a SmartPtr userdata lua object.
34 **
35 ** smartptr.new( pointer, finalizer )
36 **
37 ** @param pointer
38 ** @param finalizer function ( to be called with pointer ) or nil
39 ** @return SmartPtr userdata object
40 */
41
42 int lua_smartptr_new(lua_State *L)
43 {
44 const void *ptr;
45 int ref;
46 lua_SmartPtr *sptr;
47
48 if (lua_gettop(L) != 2)
49 luaL_error(L, "argument mismatch, usage:\n\tnewsmartptr( lightuserdata [, finalizer] )");
50
51 ptr = lua_topointer(L, 1);
52 luaL_argcheck(L, lua_isfunction(L, 2), 2, "must be a finalizer function");
53
54 ref = luaL_ref(L, LUA_REGISTRYINDEX);
55
56 sptr = (lua_SmartPtr*) lua_newuserdata(L, sizeof(lua_SmartPtr) );
57
58 sptr->pointer = ptr;
59 sptr->finalizer = ref;
60
61 luaL_getmetatable(L, LUA_SMARTPTR_TNAME);
62 lua_setmetatable(L, -2);
63
64 return 1;
65 }
66
67 /*
68 ** update finalizer value on SmartPtr object
69 **
70 ** smartptr.setfinalizer(smartptr, newfinalizer)
71 **
72 ** @param smartptr object
73 ** @param newfinalizer function or nil
74 */
75
76 int lua_smartptr_setfinalizer(lua_State *L)
77 {
78 lua_SmartPtr* sptr = (lua_SmartPtr*) luaL_checkudata(L, 1, LUA_SMARTPTR_TNAME);
79 if (lua_isnil(L, 2)) sptr->finalizer = LUA_REFNIL;
80 lua_rawseti(L, LUA_REGISTRYINDEX, sptr->finalizer);
81 return 0;
82 }
83
84 /*
85 ** call finalizer (internal through __gc event)
86 **
87 */
88
89 int lua_smartptr_callfinalizer(lua_State *L)
90 {
91 lua_SmartPtr* sptr = (lua_SmartPtr*) lua_topointer(L,1);
92 int r = sptr->finalizer;
93 if (r != LUA_REFNIL) {
94 lua_rawgeti(L, LUA_REGISTRYINDEX, r);
95 lua_pushlightuserdata(L, (void*) sptr->pointer);
96 lua_call(L, 1, 0);
97 luaL_unref(L, LUA_REGISTRYINDEX, r);
98 }
99 }
100
101 /*
102 ** get pointer value
103 **
104 ** lua_smartptr_get(smartptr)
105 **
106 ** @return lightuserdata
107 **
108 */
109
110 int lua_smartptr_get(lua_State *L)
111 {
112 lua_SmartPtr* sptr = (lua_SmartPtr*) lua_topointer(L,1);
113 lua_pushlightuserdata(L, (void*) sptr->pointer);
114 return 1;
115 }
116
117 /*
118 ** lua c function tolightuserdata(integer)
119 **
120 ** @return lightuserdata
121 **
122 */
123
124 int lua_tolightuserdata(lua_State *L)
125 {
126 lua_Number number = lua_tonumber(L, 1);
127 lua_pushlightuserdata(L, (void*) ( (unsigned long) number ) );
128 return 1;
129 }
130
131 void lua_smartptr_installmetatable(lua_State *L)
132 {
133 if ( luaL_newmetatable(L,LUA_SMARTPTR_TNAME) ) {
134 lua_pushliteral(L, "__gc");
135 lua_pushcfunction(L, lua_smartptr_callfinalizer);
136 lua_settable(L, -3);
137 lua_pushliteral(L, "__call");
138 lua_pushcfunction(L, lua_smartptr_get);
139 lua_settable(L, -3);
140 lua_pop(L,1);
141 }
142 }
143
144 static const struct luaL_Reg luareg_smartptr[] =
145 {
146 { "new", lua_smartptr_new },
147 { "setfinalizer", lua_smartptr_setfinalizer },
148 { "tolightuserdata", lua_tolightuserdata },
149 { NULL, NULL }
150 };
151
152 LUALIB_API int luaopen_smartptr(lua_State *L)
153 {
154 lua_smartptr_installmetatable(L);
155 luaL_register(L, LUA_SMARTPTR_LIBNAME, luareg_smartptr);
156 return 0;
157 }
158