Git Product home page Git Product logo

Comments (12)

kunitoki avatar kunitoki commented on September 27, 2024

Thanks for the support !

Will try to answer the questions one by one.

  • When pushing a C++ pointer to Lua is it possible to dynamically choose what exposed class to use?

Yes, if the types have been registered with LuaBridge, than it's a matter of casting to your right type (the best cast depends on the usa case and object types, static or dynamic) before sending the pointer/reference into lua (via stack push or function calls from C++).

So if you registered both class A and class B : public A (as derivedClass from A) then it's possible you dynamic_cast<B*>(my_a_pointer) in C++ and send it into luabridge, using normal RTTI in C++.

See https://kunitoki.github.io/LuaBridge3/Manual#23---class-objects for more info on how to recreate your C++ class hierarchies to be exposed to lua.

  • Can C++ exposed classes be extended in Lua?

Yes ! And only in LuaBridge3 (not in vanilla luabridge). For enabling that support, there is some boilerplate needed, but it will also allow better flexibility once you build one of such "extensible" classes. Have a look at the addIndexMetamethod and addNewIndexMetamethod which allows to expose a C++ class via beginClass and still overload __index and ___newindex lua metamethods to store and retrieve "dynamic" parameters (you should write the storage yourself in C++). https://kunitoki.github.io/LuaBridge3/Manual#27---index-and-new-index-metamethods-fallback

  • Security on possible malicious Lua scripts.

I personally have a strict way to setup my environment, and i carefully select and block environments from exposing functions i do not want a scripter to use. But there is nothing in luabridge for that, you need to do it yourself in lua at the moment. Will try to see if i can extract some of these utils and make them part of the library.

You could have a look at how i do coroutines sandboxed "envs" using LuaBridge3 getNamespaceFromStack in order to have separate env tables for each lua thread (coroutine). So a script running in a lua thread can see only what is exposed in that env table, instead of the global namespace, also a global variable in the env will not leak into the global namespace and interfere with other coroutines.

See > https://github.com/kunitoki/LuaBridge3/blob/master/Tests/Source/CoroutineTests.cpp#L82

  • What are your future plans with LuaBridge3?

Some things on the roadmap are explicited here #54 (comment)

from luabridge3.

Mellnik avatar Mellnik commented on September 27, 2024

Thank you for the answer. I've read carefully through it.

The ability to hook into __index sounds awesome. I am just in the process of migrating from the vanilla LB to LB3 here. Once that's done I will look into dynamic class extensions.

I do have one more question tho:
I am writing a Lua wrapper around a pretty big library. The library itself manages all allocation of objects and it's lifetime with a garbage collector. It is impossible to modify the existing library's classes to use RefCountedObjectPtr. I also don't really want to let Lua control the lifetime at all.
So what I did was adding a special version of the class Userdata. Instead of void* m_p I am storing a weak reference to the library objects. Furthermore I've modified all function and property calls from and to Lua to check whether the weak ref is still alive. If it was collected by the GC and is dead a Lua error is thrown.

It's pretty ugly right now. So I was wondering if you know a better alternative. I've looked into ContainerTraits but that doesn't seem to work for me. I still need to be able to push and get raw pointers.

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

You could maybe look into having lightuserdata (http://www.lua.org/pil/28.5.html) to stored full userdata objects in a weak table in the registry (https://www.lua.org/pil/17.html), you only need to register and unregister your real C++ objects into this table, but then give away lightuserdata pointers indexes into the table. If you can find a lightuserdata into the weak table, then you could access the full userdata to it, and if you don't find it, object lifetime ended on the c++ side.

The problem is what to do if your full userdata is garbage collected by C++ while you hold a local reference to it in lua:

  • you have the lightuserdata in Lua
  • query the table, got the object in Lua
  • use the object on the Lua side, which calls back into C++
  • some C++ callback triggers the garbage collector which deletes the object
  • use again the previously used object in Lua
  • boom!

from luabridge3.

Mellnik avatar Mellnik commented on September 27, 2024

To get back on the index extension feature.

  • Are the add*MetaMethod functions called on derived classes when it's registered on the base class?

  • When using your example it sometime crashes when trying call a value as a function.

MyObject.abc = true
MyObject:abc()
MyObject:xyz()
luabridge::LuaRef indexMetaMethodFunction2(MyVector& x, const luabridge::LuaRef& key, lua_State* L)
{
	UE_LOG(LogTemp, Warning, TEXT("indexMetaMethodFunction"));

	if (key.tostring() == "xyz")
	{
		if (!luabridge::push(L, "123"))
			lua_pushnil(L);
	}
	else
	{
		auto it = data.find(key);
		if (it != data.end())
			return it->second;

		lua_pushnil(L);
	}

	return luabridge::LuaRef::fromStack(L);
}
Assertion failed: equalstates(L, m_L) [LuaBridge.h] [Line: 6530]

lua_topointer() []
std::_Hash<std::_Umap_traits<luabridge::LuaRef,luabridge::LuaRef,std::_Uhash_compare<luabridge::LuaRef,std::hash<luabridge::LuaRef>,std::equal_to<luabridge::LuaRef> >,std::allocator<std::pair<luabridge::LuaRef const ,luabridge::LuaR()
indexMetaMethodFunction2() [LuaTest.cpp:558]
luabridge::detail::invoke_proxy_function<luabridge::LuaRef (__cdecl*)(MyVector &,luabridge::LuaRef const &,lua_State *)>() [LuaBridge.h:5949]
lua_yieldk()
luaD_precall()
luaM_toobig()
lua_callk()
luabridge::detail::index_metamethod() [LuaBridge.h:5497]

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

Are you working with multiple lua threads (i see a call to yield from the stack trace) ? Beware of stored LuaRef in separate lua threads (coroutines) they have different lua_State pointers (that's why equalstates assertion fails). See if moving the reference to the current thread solves it https://github.com/kunitoki/LuaBridge3/blob/master/Distribution/LuaBridge/LuaBridge.h#L7062

from luabridge3.

Mellnik avatar Mellnik commented on September 27, 2024

No but I was using a global variable and forgot to reset that. So a new luastate caused that problem.

Anyway I think it is normal that addIndexMetaMethod must be registered on the base class and won't work if it is registered in a derivedClass right? If so you should add that to the docs please.

Is it normal that when doing the following with your basic test code:

local bc = MyBaseClass(3)
bc.test = function(Value) print("Value: ", Value); end
bc:test("ok")

The test function will not print the string "ok" but it prints the userdata of bc.

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

It is normal, as you are calling via : the first argument is self, so you need to add that explicitly in the function signature

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

About the methods being used in derived classes i'm not sure that will work, i would keep it simple to avoid confusion when calling c++ methods or dynamic methods from lua (use one or the other).

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

Take a look here http://tpcg.io/_2N67Y8

from luabridge3.

Mellnik avatar Mellnik commented on September 27, 2024

I am aksing because it is so inconsistent with Userdata. Because for normal registered Userdatas it's the opposite:

MyUserdataObject:MyFunction(p1, p2, p3)

or

MyUserdataObject.MyFunction(MyUserdataObject, p1, p2, p3)

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

I don't get it, in lua this:

object:func(1)

will be rewritten as

object.func(object, 1)

from luabridge3.

Mellnik avatar Mellnik commented on September 27, 2024

Sorry for the confusion, you are absolutely right.

from luabridge3.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.