Newer
Older
Import / applications / HighwayDash / ports / Framework / LuaBindings.h
//  BlockyFroggy
//  Copyright © 2017 John Ryland.
//  All rights reserved.
#pragma once
#ifndef LUA_BINDINGS_H
#define LUA_BINDINGS_H


// Forward declare types needed
struct lua_State;
typedef int (*lua_CFunction) (lua_State *L);


void registerLuaBinding(lua_State* L, const char* name, lua_CFunction fn); // Register a single function
void registerLuaBindings(lua_State* L); // All the framework ones

// Using macro below, it is then possible to bind game specific ones
#define BIND_C_FUNTION_TO_LUA(L, func) \
    registerLuaBinding(L, #func, [](lua_State* lua)->int { return MakeCallableFunc(lua, func); } )


#include "lua-5.3.2/src/lua.h"
#include <functional>
#include <cassert>


// If we are wrapping/binding a function that returns an int, propagate the result to lua
template <typename... As, typename... Ps>
int MakeCallableFunc(lua_State*, int, int (*fn)(Ps... values), int (*)(), As... params) {
  return fn(std::forward<As>(params)...);
}

// Otherwise if the return type is not int, return 0
template <typename R, typename... As, typename... Ps>
int MakeCallableFunc(lua_State*, int, R (*fn)(Ps... values), R (*)(), As... params) {
  fn(std::forward<As>(params)...);
  return 0;
}

// Handle int arguments
template <typename R, typename... As, typename... Ts, typename... Ps>
int MakeCallableFunc(lua_State* L, int i, R (*fn)(As... values), R (*)(int, Ts... values), Ps... params) {
  R (*fn3)(Ts... values) = nullptr;
  assert(lua_isinteger(L,i));
  return MakeCallableFunc(L, i+1, fn, fn3, std::forward<Ps>(params)..., (int)lua_tointeger(L, i));
}

// Handle double arguments
template <typename R, typename... As, typename... Ts, typename... Ps>
int MakeCallableFunc(lua_State* L, int i, R (*fn)(As... values), R (*)(double, Ts... values), Ps... params) {
  R (*fn3)(Ts... values) = nullptr;
  assert(lua_isnumber(L,i));
  return MakeCallableFunc(L, i+1, fn, fn3, std::forward<Ps>(params)..., (double)lua_tonumber(L, i));
}

// Handle string arguments
template <typename R, typename... As, typename... Ts, typename... Ps>
int MakeCallableFunc(lua_State* L, int i, R (*fn)(As... values), R (*)(const char*, Ts... values), Ps... params) {
  R (*fn3)(Ts... values) = nullptr;
  assert(lua_isstring(L,i));
  return MakeCallableFunc(L, i+1, fn, fn3, std::forward<Ps>(params)..., (const char*)lua_tostring(L, i));
}

// Add helper for entry in to creating the binding
template <typename R, typename... As>
int MakeCallableFunc(lua_State* L, R (*fn)(As... values)) {
  return MakeCallableFunc(L, 1, fn, fn);
}


#endif // LUA_BINDINGS_H