Coder Social home page Coder Social logo

Comments (2)

Rochet2 avatar Rochet2 commented on July 24, 2024 2

As I see it in your code, the important part from lua seems to be that you need to only be able to bind arbitrary lua function to a signal regardless of what that signal is as long as the signal is exposed to lua.

A problem is that you cannot access templated classes without knowing the template parameters, which are the types that you cannot get from lua. You are basically required to do any binding for templated classes beforehand or you must know/have a predetermined logic to come up with the template signature in the function you bind. There are different kinds of things you can do depending on what you need. There might be some way to get around to what you need using templates, but off the top of my head I didnt come up with any that did not seem impractical (for example make a map of template instanciations that are then available to lua through a map of sorts).

Instead, here is one simple example that utilizes a inheritance to implement a non-templated base class for lua while maintaining the typed C++ counterpart in the templated subclass. It allows you to bind the functionality required by lua through the base class only once, enabling you to connect functions to any signal exposed into lua regardless of its types. Maybe its what you need, or maybe it gives you inspiration for something cooler :)

#include <limits>
#include <functional>
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
#include <iostream>

class SignalBase {
public:
  void connectLua(sol::protected_function fn) {
    luaHandlers.push_back(fn);
  }

protected:
  std::vector<sol::protected_function> luaHandlers;
};

template<class... TArgs>
class Signal : public SignalBase {
  using Handler = std::function<void(TArgs &...)>;
public:
  void connect(Handler &&handler) {
    handlers.push_back(handler);
  }

  void notify(TArgs... args) {
    for (auto handler: handlers) {
      handler(args...);
    }
    for (auto handler: luaHandlers) {
      handler(args...);
    }
  }

private:
  std::vector<Handler> handlers;
};

int main() {
    sol::state state;
    state.open_libraries();

    auto usertype = state.new_usertype<SignalBase>("Signal", sol::no_constructor);
    usertype["connect"] = &SignalBase::connectLua;

    Signal<float, uint32_t> signal;

    state["mySignal"] = std::reference_wrapper<SignalBase>(signal); // NOTE we have to cast or explicitly state here that we want SignalBase as otherwise sol will think its a different type because of the template class

    signal.connect([](float a, uint32_t b) {
      std::cout << "App: " << a << " " << b << "\n";
    });

    state.script(R"(
      mySignal:connect(function(a, b)
        print('Lua: ', a, b)
      end)
    )");

    signal.notify(10.0f, 20);

    return 0;
}

from sol2.

GasimGasimzada avatar GasimGasimzada commented on July 24, 2024

I ended up doing a a weird implementation with lambdas. One of the things that I wanted to also do was to make the lua signal "proxy" to consume the internal Signal (the example below is simplified but I pass more than just the original signal to the SolSignal class):

template<class... TArgs>
class Signal {
  using Handler = std::function<void(TArgs &...)>;
public:
  void connect(Handler &&handler) {
    auto id = handlers.size();

    handlers.push_back(handler);
  }

  void notify(TArgs... args) {
    for (auto handler: handlers) {
      handler(args...);
    }
  }

private:
  std::vector<Handler> handlers;
};

class SolSignal {
public:
  template<class... TArgs>
  SolSignal(Signal<TArgs...> &signal) {
    mConnector = [&signal](sol::protected_function fn) {
        return signal.connect([fn](TArgs &...args) {
            fn(args...);
        });
    };
  }

  SignalSlot connect(sol::protected_function fn) {
    return mConnector(fn);
  }
  
private:
  std::function<SignalSlot(sol::protected_function)> mConnector;
};

int main() {
    sol::state state;
    state.open_libraries();

    auto usertype = state.new_usertype<SolSignal>("Signal", sol::no_constructor);
    usertype["connect"] = &SolSignal::connect;

    Signal<float, uint32_t> signal;
    state["mySignal"] = SolSignal(signal);

    signal.connect([](float a, uint32_t b) {
      std::cout << "App: " << a << " " << b << "\n";
    });

    state.script(R"(
      mySignal:connect(function(a, b)
        print('Lua: ', a, b)
      end)
    )");

    signal.notify(10.0f, 20);
    return 0;
}

But I might try inheritance as well. Maybe I can make it work with it since I have kind of made my own dynamic dispatch here and if I can, I would want to use the language feature itself :)

from sol2.

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.