Mercurial > pub > dyncall > bindings
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 |