Git Product home page Git Product logo

Comments (15)

kunitoki avatar kunitoki commented on September 27, 2024

Yeah there is no special way to declare enums as types and the only way is still the old way (a stack specialization is required). The underlying type usage is just to simplify passing enums from c++ down to lua.

I'm fine having a more structured type definition for enums, where a c++ enum could be mapped to a lua one, and offer more transparent bidirectional conversion. Will look into it, thanks for reporting !

from luabridge3.

dtroitskiy avatar dtroitskiy commented on September 27, 2024

Ah, I see, then I will continue to use stack specializations.
And I guess you can close this issue whenever you feel like it.

from luabridge3.

dtroitskiy avatar dtroitskiy commented on September 27, 2024

Oh, right, one thing that would be definitely nice to fix is that case when you use it as std::map key and similar, because, like I described, there is no error message at all, and would be nice to have something similar to error you get when you try to use it as function call argument, thus at least you understand what's going on wrong more clearly.

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

I'm working on adding proper enum support in the library

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

It's kind of difficult to chose a single way to handle this, because depending on the use case this could get implemented in different ways (which might also have performance considerations).

There are two possibilities:

  • treat C++ enums as integers, and map them to lua as such. it will work but passing any unrelated lua integer to a C++ function taking an enum, it will work (even if the integer conversion can't assume a valid enum value). This is the fastest, but also the less secure (UB is just behind the corner).

  • treat C++ as userdata. Enums will have their own type on the lua side so they can be checked (you can's just call(1) from lua to a method exposed in C++ that takes a call(enum_type value), you need to use a valid userdata. This is the safest (in term of type safety) but also the slowest.

I'm considering allowing both.

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

I've pushed both wrappers for Stack, see #56

In the meanwhile i'll add docs, it would be nice if you could check if they help.

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

After trying more with the second solution, i think there are some caveats when working with lua tables and the enums are userdata, because they all have a separate address in lua land and equality is performed raw (no metamethods), so two instances of those enums objects in lua cannot be used as keys in a table (the will never match). Will investigate.

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

It doesn't seem we can workaround this with enums as separate types with their own userdata:

The indexing of tables follows the definition of raw equality in the language. The expressions a[i] and a[j]
denote the same table element if and only if i and j are raw equal (that is, equal without metamethods).
In particular, floats with integral values are equal to their respective integers (e.g., 1.0 == 1). To avoid
ambiguities, any float with integral value used as a key is converted to its respective integer. For instance,
if you write a[2.0] = true, the actual key inserted into the table will be the integer 2. (On the other hand, 2
and "2" are different Lua values and therefore denote different table entries.)

Full userdata cannot be used for indexing (every time you create an "instance" of the userdata, it will be a different object only raw equal to itself), so your example will never work when enums are mapped to userdata:

std::map<Enum, std::string> testEnumMap = {
	{ ONE, "ONE" },
	{ TWO, "TWO" },
	{ THREE, "THREE" }
};

We could use lightuserdata by hashing the enum type + value, but there are hight chances of hash collisions between enums.

from luabridge3.

dtroitskiy avatar dtroitskiy commented on September 27, 2024

Ok, so as I understand, first solution, i.e. "treat C++ enums as integers" would be in favor right now?
Yeah, second one sounded a bit more more correct to me, I'd say, but if it's problematic, then first also works for me no problem.
If, thanks to stack specializations, type conversion will always work fine when calling something Lua => C++, then it sounds good enough.

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

See this discussion http://lua-users.org/lists/lua-l/2007-01/msg00126.html apparently the only way is to implement a userdata cache in the form of weak table in the registry that will return references to existing userdata instances when they are already there, or being populated when not there. Sounds interesting but it's also a bit demanding both in term of space and time complexity.

from luabridge3.

dtroitskiy avatar dtroitskiy commented on September 27, 2024

I see. Despite that I'm not too good in Lua C API internals, I understand more or less what is discussed there.
Well, okay, I leave this entirely up to you to decide. If you find time to experiment with this userdata cache, then it has a chance to provide some decent outcome or at least some useful experience, I guess. Alternatively, like I said, using stack specializations is not a problem for me personally, although yeah, it's a bit of additional manual work, but not too much.

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

I found a way to make sure the conversion can be made. It's a bit more tedious, but i've now moved the enum wrapper class for stack into the library, so you should write:

enum class MyEnum
{
    A,
    B,
    C
};

template <>
struct luabridge::Stack<EnumType> : luabridge::Enum<EnumType,
                                                    EnumType::A,
                                                    EnumType::B,
                                                    EnumType::C>
{
};

This way i can check in Stack::get that the passed integer is convertible to one of the mapped enum values, and if not present raise a lua error.

from luabridge3.

dtroitskiy avatar dtroitskiy commented on September 27, 2024

Just tested, works great, thanks for your efforts!

Couple minor things.
I had to add #include <system_error>, because otherwise I had error : no type named 'error_code' in namespace 'std'.
And in docs I noticed in the sentence "This will map the enum to an integer to as int16_t" second "to" is probably not needed.
And also formatting is bit broken there, because heading "2.10 - lua_State" starts inside block of code.

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

Yeah i noticed i did some mistakes in the manual, will try to fix them asap

from luabridge3.

kunitoki avatar kunitoki commented on September 27, 2024

#58
#59

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.