File class.hpp
File List > include > simplesquirrel > class.hpp
Go to the documentation of this file.
#pragma once
#ifndef SSQ_CLASS_HEADER_H
#define SSQ_CLASS_HEADER_H
#include <functional>
#include "function.hpp"
#include "binding.hpp"
namespace ssq {
class SSQ_API Class : public Object {
public:
template<class Signature>
struct Ctor;
template<class T, class... Args>
struct Ctor<T(Args...)> {
static T* allocate(Args&&... args) {
return new T(std::forward<Args>(args)...);
}
};
Class();
virtual ~Class() = default;
Class(HSQUIRRELVM vm);
explicit Class(const Object& object);
Class(const Class& other);
Class(Class&& other) NOEXCEPT;
void swap(Class& other) NOEXCEPT;
Function findFunc(const char* name) const;
template <typename Return, typename Object, typename... Args>
Function addFunc(const char* name, const std::function<Return(Object*, Args...)>& func, bool isStatic = false) {
if (vm == nullptr) throw RuntimeException("VM is not initialised");
Function ret(vm);
sq_pushobject(vm, obj);
detail::addMemberFunc(vm, name, func, isStatic);
sq_pop(vm, 1);
return ret;
}
template <typename Return, typename Object, typename... Args>
Function addFunc(const char* name, Return(Object::*memfunc)(Args...), bool isStatic = false) {
auto func = std::function<Return(Object*, Args...)>(std::mem_fn(memfunc));
return addFunc(name, func, isStatic);
}
template <typename Return, typename Object, typename... Args>
Function addFunc(const char* name, Return(Object::*memfunc)(Args...) const, bool isStatic = false) {
auto func = std::function<Return(Object*, Args...)>(std::mem_fn(memfunc));
return addFunc(name, func, isStatic);
}
template<typename F>
Function addFunc(const char* name, const F& lambda, bool isStatic = false) {
return addFunc(name, detail::make_function(lambda), isStatic);
}
template<typename T, typename V>
void addVar(const std::string& name, V T::* ptr, bool isStatic = false) {
findTable("_get", tableGet, dlgGetStub);
findTable("_set", tableSet, dlgSetStub);
bindVar<T, V>(name, ptr, tableGet.getRaw(), varGetStub<T, V>, isStatic);
bindVar<T, V>(name, ptr, tableSet.getRaw(), varSetStub<T, V>, isStatic);
}
template<typename T, typename V>
void addConstVar(const std::string& name, V T::* ptr, bool isStatic = false) {
findTable("_get", tableGet, dlgGetStub);
bindVar<T, V>(name, ptr, tableGet.getRaw(), varGetStub<T, V>, isStatic);
}
Class& operator = (const Class& other);
Class& operator = (Class&& other) NOEXCEPT;
protected:
void findTable(const char* name, Object& table, SQFUNCTION dlg) const;
static SQInteger dlgGetStub(HSQUIRRELVM vm);
static SQInteger dlgSetStub(HSQUIRRELVM vm);
template<typename T, typename V>
void bindVar(const std::string& name, V T::* ptr, HSQOBJECT& table, SQFUNCTION stub, bool isStatic) {
auto rst = sq_gettop(vm);
sq_pushobject(vm, table);
sq_pushstring(vm, name.c_str(), name.size());
auto vp = sq_newuserdata(vm, sizeof(ptr));
std::memcpy(vp, &ptr, sizeof(ptr));
sq_newclosure(vm, stub, 1);
if (SQ_FAILED(sq_newslot(vm, -3, isStatic))) {
throw TypeException("Failed to bind member variable to class");
}
sq_pop(vm, 1);
sq_settop(vm, rst);
}
template<typename T, typename V>
static SQInteger varGetStub(HSQUIRRELVM vm) {
T* ptr;
sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*>(&ptr), nullptr);
typedef V T::*M;
M* memberPtr = nullptr;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&memberPtr), nullptr);
M member = *memberPtr;
detail::push(vm, ptr->*member);
return 1;
}
template<typename T, typename V>
static SQInteger varSetStub(HSQUIRRELVM vm) {
T* ptr;
sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*>(&ptr), nullptr);
typedef V T::*M;
M* memberPtr = nullptr;
sq_getuserdata(vm, -1, reinterpret_cast<SQUserPointer*>(&memberPtr), nullptr);
M member = *memberPtr;
ptr->*member = detail::pop<V>(vm, 2);
return 0;
}
Object tableSet;
Object tableGet;
};
#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace detail {
template<>
inline Class popValue(HSQUIRRELVM vm, SQInteger index){
checkType(vm, index, OT_CLASS);
Class val(vm);
if (SQ_FAILED(sq_getstackobj(vm, index, &val.getRaw()))) throw TypeException("Could not get Class from squirrel stack");
sq_addref(vm, &val.getRaw());
return val;
}
}
#endif
}
#endif