annotate lua/luadyncall/src/smartptr.c @ 54:918dab7a6606

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