diff options
author | Robin Gareus <robin@gareus.org> | 2019-04-12 04:12:22 +0200 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2019-04-12 05:45:27 +0200 |
commit | 3da07e6736bfc79fa4f61b58a65f025e0fa88c62 (patch) | |
tree | 6e73ebee200d5d2f9f78578e2e2bf532579b3a3a /libs/lua | |
parent | 8dc883ebfac1560917948bc30f7f69cb8f76fc97 (diff) |
Special case Lua copy-construction of trackable instances
This fixes an crashing issue with ArdourUI.SelectionList a bug
introduced in 6dc3bdf252c and 35dcd46d7d.
Since removal of the special cases in 35dcd46d7d, when using
a C-pointer in a std::list<>,
std::list<class*>::push_back(TypeListValue)
TypeListValues<>'s Head was expanded to "class*& const"
implied by void ::push_back(const T& value);
This resulted in lifetime issues with a classes that derive
from sigc::trackable (e.g. Ardour's Selection).
The reference leaves scope and isn't duplicated when it is pushed back
to the std::list<>.
The script scripts/select_every_2nd_region.lua crashed because entries
in the SelectionList were no longer valid.
Previously (before 6dc3bdf252c) TypeListValues explicitly
copy-constructed the value to work around the lifetime issue.
This new solution bypasses the issue by directly using the c-pointer
without dereferencing it.
Diffstat (limited to 'libs/lua')
-rw-r--r-- | libs/lua/LuaBridge/detail/CFunctions.h | 14 | ||||
-rw-r--r-- | libs/lua/LuaBridge/detail/Namespace.h | 2 |
2 files changed, 15 insertions, 1 deletions
diff --git a/libs/lua/LuaBridge/detail/CFunctions.h b/libs/lua/LuaBridge/detail/CFunctions.h index 7300e9cb70..22dc115a6a 100644 --- a/libs/lua/LuaBridge/detail/CFunctions.h +++ b/libs/lua/LuaBridge/detail/CFunctions.h @@ -1234,6 +1234,20 @@ struct CFunc } //-------------------------------------------------------------------------- + // push back a C-pointer to a std::list<T*> + + template <class T, class C> + static int pushbackptr (lua_State *L) + { + C * const c = Userdata::get <C> (L, 1, false); + if (!c) { return luaL_error (L, "invalid pointer to std::list<>"); } + T * const v = Userdata::get <T> (L, 2, true); + if (!v) { return luaL_error (L, "invalid pointer to std::list<>::value_type"); } + c->push_back (v); + return 0; + } + + //-------------------------------------------------------------------------- // generate std::map from table template <class K, class V> diff --git a/libs/lua/LuaBridge/detail/Namespace.h b/libs/lua/LuaBridge/detail/Namespace.h index 5ea139ee22..76474aa703 100644 --- a/libs/lua/LuaBridge/detail/Namespace.h +++ b/libs/lua/LuaBridge/detail/Namespace.h @@ -1911,7 +1911,7 @@ public: typedef std::list<TP> LT; return beginConstStdCPtrList<T> (name) .addFunction ("unique", (void (LT::*)())<::unique) - .addFunction ("push_back", (void (LT::*)(const TP&))<::push_back); + .addExtCFunction ("push_back", &CFunc::pushbackptr<T, LT>); } |