12

According to the LuaBridge readme, LuaBridge does not support "Enumerated constants", which I assume is just enums. Since sf::Event is almost entirely enums, is there any way I can expose the class? Currently the only other solution I can come up with is detect key presses in C++, then send a string to Lua, that describes the event. Obviously, there are around 100+ keys on a modern keyboard, which would cause a massive, ugly segment of just if statements.

For those who haven't used SFML: Link to sf::Event class source code


UPDATE:

After attempting to create the function outlined in my question, I discovered that it don't work anyway, because you can't return more than one string in C++, so most events are ignored.

Example Source (doesn't work):

std::string getEvent()
{
    sf::Event event;
    while (window.pollEvent(event))
    {
        if (event.type == sf::Event::Closed) {window.close(); return "";}
        else if (event.type == sf::Event::GainedFocus) {return "GainedFocus";}
        else if (event.type == sf::Event::LostFocus) {return "LostFocus";}
        else if (event.type == sf::Event::Resized) {return "Resized";}
        else if (event.type == sf::Event::TextEntered)
        {
            if ((event.text.unicode < 128) && (event.text.unicode > 0)) {return "" + static_cast<char>(event.text.unicode);}
        }
        else if (event.type == sf::Event::KeyPressed)
        {
            //If else for all keys on keyboard
        }
        else if (event.type == sf::Event::KeyReleased)
        {
            //If else for all keys on keyboard
        }
        else {return "";}
    }
    return "";
}

UPDATE UPDATE:

Since this question has received zero comments or answers, I've decided not to rule out other libraries. So, if there is a C++ library that supports enums, I will accept it

Community
  • 1
  • 1
Ben Hollier
  • 585
  • 2
  • 11
  • 32
  • 1
    An enum is just named constants, which you can export as a Lua table. No if statements required. I don't know LuaBridge, but scanning their docs it looks like you could expose EventType via a member proxy, then just return a LuaTable that you've initialized with the enumeration key/values. You can create a macro using the stringizing operator to do most of the typing for you. – Mud Jul 23 '15 at 22:21
  • 1
    The enum is not the difficult problem here. I think that handling the union and the composite member variables correctly is much more complicated. I'd be very impressed if there is a binding generator out there that can do it (or even one of those) ... – siffiejoe Jul 24 '15 at 12:21
  • 1
    @siffiejoe The memory layout of the C++ object has no effect on the complexity of the binding. The object is just a pointer, to both the C++ code and the Lua code, and the offset math for member access is a detail handled by the C++ compiler. – Mud Jul 24 '15 at 21:05
  • @Mud: The lifetime of the member-userdata depends on the lifetime of the main-userdata. The member-userdata doesn't free its memory, because it is owned by someone else (the main-userdata), and if the main-userdata is collected before the member-userdata, you will get a dangling pointer in the member-userdata. – siffiejoe Jul 24 '15 at 23:40
  • @siffiejoe o.O That has nothing to do with your previous comment, or anything I've said in this thread. When you export a pointer to Lua via userdata, you create a `__gc` metamethod so you can free the C++ memory when the Lua userdata is garbage collected. That has absolutely nothing to do with whether or not that C++ object is a union. The fact the the object may contain unions or bitfields or packing/alignment pragmas has no bearing whatsoever on this discussion in any way. – Mud Jul 25 '15 at 08:04
  • @Mud: ??? sf:Event contains a union of structs (by value). LuaBridge can't handle either correctly for the reasons I gave in my comment. I don't think there is a binding generator that can, but as I said I'd be happy to be wrong on this one. Why is this not relevant? – siffiejoe Jul 25 '15 at 18:11
  • @siffiejoe You've yet to give a reason why a binding generator can't (in fact there are several binding generators that *do*), but you did go off on a bizarre, irrelevant tangent about "lifetime of member-userdata". – Mud Jul 26 '15 at 00:53
  • @Mud: Great! Would you mind giving an example, so I can see for myself? Preferably one which also handles enums, so that the OP is happy as well. And I never said *can't*, I just said that those I know *don't*, and that I'd be genuinely impressed if there are any that do! My guess is that most don't because it's a rare use case, yet it complicates the userdata handling of all classes/structs. Btw., by "member-userdata" I meant a userdata representing a member variable of struct/class/union type that's embedded by value in another object (represented by "main-userdata"). – siffiejoe Jul 26 '15 at 09:13
  • If the question is less about `sf::Event`, and more about objects with Unions and Enums in general, should I edit the question to remove all references to SFML? (that's if the reason the question got no answers was because the SFML tag scared people off) – Ben Hollier Aug 01 '15 at 09:51
  • And I'm also considering removing LuaBridge and making it about how to do it with the normal Lua C API or any other binding generator, since I can't find anything about C++ Unions with Lua (Google only showed SO questions because there is a hot network question about the soviet *union*!) – Ben Hollier Aug 01 '15 at 10:05
  • I decided to create a [new question](http://stackoverflow.com/questions/31796626/how-to-expose-c-unions-to-lua), which I will use to answer this question, if the other question gets an answer. – Ben Hollier Aug 03 '15 at 21:02

3 Answers3

2

Since this question has received zero comments or answers, I've decided not to rule out other libraries. So, if there is a C++ library that supports enums, I will accept it

The Thor library, an SFML extension, supports conversions between SFML key types and strings. This would help you serialize enumerators and pass them as strings to Lua -- and back if you need.

TheOperator
  • 5,936
  • 29
  • 42
1

if you only want enum to number, consider this. <luabridge/detail/Vector.h> methods.

#include <LuaBridge/detail/Stack.h>
enum class LogLevels { LOG_1, LOG_2 }  

namespace luabridge
{
    template <>
    struct Stack<LogLevels>
    {
        static void push(lua_State* L, LogLevels const& v) { lua_pushnumber( L, static_cast<int>(v) ); }
        static LogLevels get(lua_State* L, int index) { return LuaRef::fromStack(L, index); }
    };
}
HaruGakka
  • 11
  • 2
0

Add this into Namespace class:

template<class T>
Namespace& addConstant(char const* name, T value)
{
    if (m_stackSize == 1)
    {
        throw std::logic_error("addConstant () called on global namespace");
    }

    assert(lua_istable(L, -1)); // Stack: namespace table (ns)

    Stack<T>::push(L,value); // Stack: ns, value
    rawsetfield(L, -2, name); // Stack: ns

    return *this;
}

Then use:

getGlobalNamespace(L)
    .addNamespace("sf")
        .addNamespace("Event")
            .addConstant("KeyPressed",sf::Event::KeyPressed)
            //....
        .endNamespace()
    .endNamespace();