2020-12-11 17:07:20 +02:00
|
|
|
/* WirePlumber
|
|
|
|
|
*
|
|
|
|
|
* Copyright © 2020 Collabora Ltd.
|
|
|
|
|
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "wplua.h"
|
2020-12-18 18:25:43 +02:00
|
|
|
#include "private.h"
|
2020-12-11 17:07:20 +02:00
|
|
|
#include <wp/wp.h>
|
|
|
|
|
|
|
|
|
|
typedef struct _WpLuaClosure WpLuaClosure;
|
|
|
|
|
struct _WpLuaClosure
|
|
|
|
|
{
|
|
|
|
|
GClosure closure;
|
|
|
|
|
int func_ref;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_wplua_closure_marshal (GClosure *closure, GValue *return_value,
|
|
|
|
|
guint n_param_values, const GValue *param_values,
|
|
|
|
|
gpointer invocation_hint, gpointer marshal_data)
|
|
|
|
|
{
|
|
|
|
|
lua_State *L = closure->data;
|
|
|
|
|
int func_ref = ((WpLuaClosure *) closure)->func_ref;
|
|
|
|
|
|
|
|
|
|
/* invalid closure, skip it */
|
|
|
|
|
if (func_ref == LUA_NOREF || func_ref == LUA_REFNIL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* clear the stack and stop the garbage collector for now */
|
|
|
|
|
lua_settop (L, 0);
|
|
|
|
|
lua_gc (L, LUA_GCSTOP, 0);
|
|
|
|
|
|
|
|
|
|
/* push the function */
|
|
|
|
|
lua_rawgeti (L, LUA_REGISTRYINDEX, func_ref);
|
|
|
|
|
|
|
|
|
|
/* push arguments */
|
|
|
|
|
for (guint i = 0; i < n_param_values; i++)
|
|
|
|
|
wplua_gvalue_to_lua (L, ¶m_values[i]);
|
|
|
|
|
|
|
|
|
|
/* call in protected mode */
|
2020-12-18 18:25:43 +02:00
|
|
|
int res = _wplua_pcall (L, n_param_values, return_value ? 1 : 0);
|
2020-12-11 17:07:20 +02:00
|
|
|
|
|
|
|
|
/* handle the result */
|
|
|
|
|
if (res == LUA_OK && return_value && lua_gettop (L) >= 1)
|
|
|
|
|
wplua_lua_to_gvalue (L, 1, return_value);
|
|
|
|
|
|
|
|
|
|
/* clear the stack and clean up */
|
|
|
|
|
lua_settop (L, 0);
|
|
|
|
|
lua_gc (L, LUA_GCCOLLECT, 0);
|
|
|
|
|
lua_gc (L, LUA_GCRESTART, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_wplua_closure_invalidate (lua_State *L, WpLuaClosure *c)
|
|
|
|
|
{
|
|
|
|
|
wp_trace_boxed (G_TYPE_CLOSURE, c, "invalidated");
|
|
|
|
|
luaL_unref (L, LUA_REGISTRYINDEX, c->func_ref);
|
|
|
|
|
c->func_ref = LUA_NOREF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* wplua_function_to_closure:
|
|
|
|
|
*
|
|
|
|
|
* Make a GClosure out of a Lua function at index @idx
|
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer floating): the new closure
|
|
|
|
|
*/
|
|
|
|
|
GClosure *
|
|
|
|
|
wplua_function_to_closure (lua_State *L, int idx)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (lua_isfunction(L, idx), NULL);
|
|
|
|
|
|
|
|
|
|
GClosure *c = g_closure_new_simple (sizeof (WpLuaClosure), L);
|
|
|
|
|
WpLuaClosure *wlc = (WpLuaClosure *) c;
|
|
|
|
|
GPtrArray *closures;
|
|
|
|
|
|
2020-12-16 23:19:07 +02:00
|
|
|
lua_pushliteral (L, "wplua_closures");
|
|
|
|
|
lua_gettable (L, LUA_REGISTRYINDEX);
|
2020-12-11 17:07:20 +02:00
|
|
|
closures = wplua_toboxed (L, -1);
|
|
|
|
|
lua_pop (L, 1);
|
|
|
|
|
|
|
|
|
|
lua_pushvalue (L, idx);
|
|
|
|
|
wlc->func_ref = luaL_ref (L, LUA_REGISTRYINDEX);
|
|
|
|
|
|
|
|
|
|
wp_trace_boxed (G_TYPE_CLOSURE, c, "created, func_ref = %d", wlc->func_ref);
|
|
|
|
|
|
|
|
|
|
g_closure_set_marshal (c, _wplua_closure_marshal);
|
|
|
|
|
g_closure_add_invalidate_notifier (c, L,
|
|
|
|
|
(GClosureNotify) _wplua_closure_invalidate);
|
|
|
|
|
|
|
|
|
|
/* keep a ref in lua, so that we can invalidate
|
|
|
|
|
the closure when lua_State closes */
|
|
|
|
|
g_ptr_array_add (closures, g_closure_ref (c));
|
|
|
|
|
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_wplua_closure_destroy (GClosure * c)
|
|
|
|
|
{
|
|
|
|
|
g_closure_invalidate (c);
|
|
|
|
|
g_closure_unref (c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
_wplua_init_closure (lua_State *L)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *a = g_ptr_array_new_with_free_func (
|
|
|
|
|
(GDestroyNotify) _wplua_closure_destroy);
|
2020-12-16 23:19:07 +02:00
|
|
|
lua_pushliteral (L, "wplua_closures");
|
2020-12-11 17:07:20 +02:00
|
|
|
wplua_pushboxed (L, G_TYPE_PTR_ARRAY, a);
|
2020-12-16 23:19:07 +02:00
|
|
|
lua_settable (L, LUA_REGISTRYINDEX);
|
2020-12-11 17:07:20 +02:00
|
|
|
}
|