2013-09-01 14:27:21 +00:00
|
|
|
/*
|
|
|
|
** binding-util.h
|
|
|
|
**
|
|
|
|
** This file is part of mkxp.
|
|
|
|
**
|
|
|
|
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
|
|
|
**
|
|
|
|
** mkxp is free software: you can redistribute it and/or modify
|
|
|
|
** it under the terms of the GNU General Public License as published by
|
|
|
|
** the Free Software Foundation, either version 2 of the License, or
|
|
|
|
** (at your option) any later version.
|
|
|
|
**
|
|
|
|
** mkxp is distributed in the hope that it will be useful,
|
|
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
** GNU General Public License for more details.
|
|
|
|
**
|
|
|
|
** You should have received a copy of the GNU General Public License
|
|
|
|
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef BINDINGUTIL_H
|
|
|
|
#define BINDINGUTIL_H
|
|
|
|
|
2014-08-09 18:12:06 +00:00
|
|
|
#include "exception.h"
|
|
|
|
|
2013-12-04 16:48:37 +00:00
|
|
|
#include <mruby.h>
|
|
|
|
#include <mruby/data.h>
|
|
|
|
#include <mruby/variable.h>
|
|
|
|
#include <mruby/class.h>
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
|
|
enum CommonSymbol
|
|
|
|
{
|
2014-08-09 08:38:42 +00:00
|
|
|
CSfont = 0,
|
2013-09-01 14:27:21 +00:00
|
|
|
CSviewport,
|
|
|
|
CSbitmap,
|
|
|
|
CScolor,
|
|
|
|
CStone,
|
|
|
|
CSrect,
|
|
|
|
CSsrc_rect,
|
|
|
|
CStileset,
|
|
|
|
CSautotiles,
|
|
|
|
CSmap_data,
|
|
|
|
CSflash_data,
|
|
|
|
CSpriorities,
|
|
|
|
CSwindowskin,
|
|
|
|
CScontents,
|
|
|
|
CScursor_rect,
|
|
|
|
CSpath,
|
|
|
|
CSarray,
|
|
|
|
CSdefault_color,
|
2014-08-09 16:35:01 +00:00
|
|
|
CSchildren,
|
|
|
|
CSdispose,
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
CommonSymbolsMax
|
|
|
|
};
|
|
|
|
|
|
|
|
enum MrbException
|
|
|
|
{
|
|
|
|
Shutdown = 0,
|
|
|
|
RGSS,
|
|
|
|
PHYSFS,
|
|
|
|
SDL,
|
2013-09-03 13:22:00 +00:00
|
|
|
MKXP,
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
ErrnoE2BIG,
|
|
|
|
ErrnoEACCES,
|
|
|
|
ErrnoEAGAIN,
|
|
|
|
ErrnoEBADF,
|
|
|
|
ErrnoECHILD,
|
|
|
|
ErrnoEDEADLOCK,
|
|
|
|
ErrnoEDOM,
|
|
|
|
ErrnoEEXIST,
|
|
|
|
ErrnoEINVAL,
|
|
|
|
ErrnoEMFILE,
|
|
|
|
ErrnoENOENT,
|
|
|
|
ErrnoENOEXEC,
|
|
|
|
ErrnoENOMEM,
|
|
|
|
ErrnoENOSPC,
|
|
|
|
ErrnoERANGE,
|
|
|
|
ErrnoEXDEV,
|
|
|
|
|
|
|
|
IO,
|
|
|
|
|
|
|
|
TypeError,
|
|
|
|
ArgumentError,
|
|
|
|
|
|
|
|
MrbExceptionsMax
|
|
|
|
};
|
|
|
|
|
|
|
|
struct MrbData
|
|
|
|
{
|
|
|
|
RClass *exc[MrbExceptionsMax];
|
|
|
|
/* I'll leave the usage of these syms to later,
|
|
|
|
* so I can measure how much of a speed difference they make */
|
|
|
|
mrb_sym symbols[CommonSymbolsMax];
|
|
|
|
|
2014-08-09 17:15:54 +00:00
|
|
|
mrb_value buttoncodeHash;
|
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
MrbData(mrb_state *mrb);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Exception;
|
|
|
|
|
|
|
|
void
|
|
|
|
raiseMrbExc(mrb_state *mrb, const Exception &exc);
|
|
|
|
|
|
|
|
inline MrbData*
|
|
|
|
getMrbData(mrb_state *mrb)
|
|
|
|
{
|
|
|
|
return static_cast<MrbData*>(mrb->ud);
|
|
|
|
}
|
|
|
|
|
2014-07-19 00:22:22 +00:00
|
|
|
inline RClass*
|
|
|
|
defineClass(mrb_state *mrb, const char *name)
|
|
|
|
{
|
2014-08-09 08:38:42 +00:00
|
|
|
RClass *klass = mrb_define_class(mrb, name, mrb->object_class);
|
|
|
|
MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
|
|
|
|
|
|
|
|
return klass;
|
2014-07-19 00:22:22 +00:00
|
|
|
}
|
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
#define GUARD_EXC(exp) \
|
|
|
|
{ try { exp } catch (Exception &exc) { raiseMrbExc(mrb, exc); } }
|
|
|
|
|
|
|
|
#define DECL_TYPE(_Type) \
|
|
|
|
extern const mrb_data_type _Type##Type
|
|
|
|
|
|
|
|
#define DEF_TYPE(_Type) \
|
|
|
|
extern const mrb_data_type _Type##Type = \
|
|
|
|
{ \
|
|
|
|
#_Type, \
|
|
|
|
freeInstance<_Type> \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MRB_METHOD_PUB(name) \
|
|
|
|
mrb_value name(mrb_state *mrb, mrb_value self)
|
|
|
|
|
|
|
|
#define MRB_METHOD(name) static MRB_METHOD_PUB(name)
|
|
|
|
|
2013-09-03 09:06:01 +00:00
|
|
|
#define MRB_FUNCTION(name) \
|
|
|
|
static mrb_value name(mrb_state *mrb, mrb_value)
|
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
#define MRB_UNUSED_PARAM \
|
|
|
|
{ (void) mrb; (void) self; }
|
|
|
|
|
2013-09-03 09:06:01 +00:00
|
|
|
#define MRB_FUN_UNUSED_PARAM { (void) mrb; }
|
|
|
|
|
2013-09-01 14:27:21 +00:00
|
|
|
#define DEF_PROP_OBJ(Klass, PropKlass, PropName, prop_iv) \
|
|
|
|
MRB_METHOD(Klass##Get##PropName) \
|
|
|
|
{ \
|
2014-08-09 16:35:01 +00:00
|
|
|
checkDisposed(mrb, self); \
|
2013-09-01 14:27:21 +00:00
|
|
|
return getProperty(mrb, self, prop_iv); \
|
|
|
|
} \
|
|
|
|
MRB_METHOD(Klass##Set##PropName) \
|
|
|
|
{ \
|
|
|
|
Klass *k = getPrivateData<Klass>(mrb, self); \
|
|
|
|
mrb_value propObj; \
|
|
|
|
PropKlass *prop; \
|
|
|
|
mrb_get_args(mrb, "o", &propObj); \
|
|
|
|
prop = getPrivateDataCheck<PropKlass>(mrb, propObj, PropKlass##Type); \
|
|
|
|
GUARD_EXC( k->set##PropName(prop); ) \
|
|
|
|
setProperty(mrb, self, prop_iv, propObj); \
|
|
|
|
return propObj; \
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Object property with allowed NIL */
|
|
|
|
#define DEF_PROP_OBJ_NIL(Klass, PropKlass, PropName, prop_iv) \
|
|
|
|
MRB_METHOD(Klass##Get##PropName) \
|
|
|
|
{ \
|
|
|
|
return getProperty(mrb, self, prop_iv); \
|
|
|
|
} \
|
|
|
|
MRB_METHOD(Klass##Set##PropName) \
|
|
|
|
{ \
|
|
|
|
Klass *k = getPrivateData<Klass>(mrb, self); \
|
|
|
|
mrb_value propObj; \
|
|
|
|
PropKlass *prop; \
|
|
|
|
mrb_get_args(mrb, "o", &propObj); \
|
|
|
|
if (mrb_nil_p(propObj)) \
|
|
|
|
prop = 0; \
|
|
|
|
else \
|
|
|
|
prop = getPrivateDataCheck<PropKlass>(mrb, propObj, PropKlass##Type); \
|
|
|
|
GUARD_EXC( k->set##PropName(prop); ) \
|
|
|
|
setProperty(mrb, self, prop_iv, propObj); \
|
|
|
|
return mrb_nil_value(); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DEF_PROP(Klass, mrb_type, PropName, arg_type, conv_t) \
|
|
|
|
MRB_METHOD(Klass##Get##PropName) \
|
|
|
|
{ \
|
|
|
|
Klass *k = getPrivateData<Klass>(mrb, self); \
|
|
|
|
return mrb_##conv_t##_value(k->get##PropName()); \
|
|
|
|
} \
|
|
|
|
MRB_METHOD(Klass##Set##PropName) \
|
|
|
|
{ \
|
|
|
|
Klass *k = getPrivateData<Klass>(mrb, self); \
|
|
|
|
mrb_type value; \
|
|
|
|
mrb_get_args(mrb, arg_type, &value); \
|
|
|
|
GUARD_EXC( k->set##PropName(value); ) \
|
|
|
|
return mrb_##conv_t##_value(value); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DEF_PROP_I(Klass, PropName) \
|
|
|
|
DEF_PROP(Klass, mrb_int, PropName, "i", fixnum)
|
|
|
|
|
|
|
|
#define DEF_PROP_F(Klass, PropName) \
|
|
|
|
DEF_PROP(Klass, mrb_float, PropName, "f", _float)
|
|
|
|
|
|
|
|
#define DEF_PROP_B(Klass, PropName) \
|
|
|
|
DEF_PROP(Klass, mrb_bool, PropName, "b", bool)
|
|
|
|
|
2014-08-09 18:12:06 +00:00
|
|
|
#define INITCOPY_FUN(Klass) \
|
|
|
|
MRB_METHOD(Klass##InitializeCopy) \
|
2013-09-01 14:27:21 +00:00
|
|
|
{ \
|
2014-08-09 18:12:06 +00:00
|
|
|
mrb_value origObj; \
|
|
|
|
mrb_get_args(mrb, "o", &origObj); \
|
|
|
|
Klass *orig = getPrivateData<Klass>(mrb, origObj); \
|
|
|
|
Klass *k = 0; \
|
|
|
|
GUARD_EXC( k = new Klass(*orig); ) \
|
|
|
|
setPrivateData(self, k, Klass##Type); \
|
|
|
|
return self; \
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define MARSH_LOAD_FUN(Klass) \
|
|
|
|
MRB_METHOD(Klass##Load) \
|
|
|
|
{ \
|
|
|
|
return objectLoad<Klass>(mrb, self, Klass##Type); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_PROP_BIND(Klass, PropName, prop_name_s) \
|
|
|
|
{ \
|
|
|
|
mrb_define_method(mrb, klass, prop_name_s, Klass##Get##PropName, MRB_ARGS_NONE()); \
|
|
|
|
mrb_define_method(mrb, klass, prop_name_s "=", Klass##Set##PropName, MRB_ARGS_REQ(1)); \
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline mrb_value
|
|
|
|
mrb__float_value(mrb_float f)
|
|
|
|
{
|
2014-04-14 07:39:23 +00:00
|
|
|
mrb_value v;
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2014-07-19 00:22:22 +00:00
|
|
|
SET_FLOAT_VALUE(0, v, f);
|
2014-04-14 07:39:23 +00:00
|
|
|
return v;
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline mrb_sym
|
|
|
|
getSym(mrb_state *mrb, CommonSymbol sym)
|
|
|
|
{
|
|
|
|
return getMrbData(mrb)->symbols[sym];
|
|
|
|
}
|
|
|
|
|
2014-08-09 16:35:01 +00:00
|
|
|
void
|
|
|
|
raiseDisposedAccess(mrb_state *mrb, mrb_value self);
|
|
|
|
|
|
|
|
inline void checkDisposed(mrb_state *mrb, mrb_value self)
|
|
|
|
{
|
|
|
|
if (!DATA_PTR(self))
|
|
|
|
raiseDisposedAccess(mrb, self);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class C>
|
|
|
|
inline C *
|
2013-09-01 14:27:21 +00:00
|
|
|
getPrivateData(mrb_state *mrb, mrb_value self)
|
|
|
|
{
|
2014-08-09 16:35:01 +00:00
|
|
|
C *c = static_cast<C*>(DATA_PTR(self));
|
|
|
|
|
|
|
|
if (!c)
|
|
|
|
raiseDisposedAccess(mrb, self);
|
|
|
|
|
|
|
|
return c;
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline T *
|
|
|
|
getPrivateDataCheck(mrb_state *mrb, mrb_value obj, const mrb_data_type &type)
|
|
|
|
{
|
2014-08-09 16:35:01 +00:00
|
|
|
void *ptr = mrb_check_datatype(mrb, obj, &type);
|
|
|
|
return static_cast<T*>(ptr);
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
2014-08-09 08:38:42 +00:00
|
|
|
setPrivateData(mrb_value self, void *p, const mrb_data_type &type)
|
2013-09-01 14:27:21 +00:00
|
|
|
{
|
2014-08-09 08:38:42 +00:00
|
|
|
DATA_PTR(self) = p;
|
|
|
|
DATA_TYPE(self) = &type;
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline mrb_value
|
|
|
|
wrapObject(mrb_state *mrb, void *p, const mrb_data_type &type)
|
|
|
|
{
|
2014-08-09 08:38:42 +00:00
|
|
|
RClass *klass = mrb_class_get(mrb, type.struct_name);
|
|
|
|
RData *data = mrb_data_object_alloc(mrb, klass, p, &type);
|
|
|
|
mrb_value obj = mrb_obj_value(data);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
2014-08-09 08:38:42 +00:00
|
|
|
setPrivateData(obj, p, type);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
wrapProperty(mrb_state *mrb, mrb_value self,
|
|
|
|
void *prop, CommonSymbol iv, const mrb_data_type &type)
|
|
|
|
{
|
|
|
|
mrb_value propObj = wrapObject(mrb, prop, type);
|
|
|
|
|
|
|
|
mrb_obj_iv_set(mrb,
|
|
|
|
mrb_obj_ptr(self),
|
|
|
|
getSym(mrb, iv),
|
2014-04-14 07:39:23 +00:00
|
|
|
propObj);
|
2013-09-01 14:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline mrb_value
|
|
|
|
getProperty(mrb_state *mrb, mrb_value self, CommonSymbol iv)
|
|
|
|
{
|
|
|
|
return mrb_obj_iv_get(mrb,
|
|
|
|
mrb_obj_ptr(self),
|
|
|
|
getSym(mrb, iv));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
setProperty(mrb_state *mrb, mrb_value self,
|
|
|
|
CommonSymbol iv, mrb_value propObject)
|
|
|
|
{
|
|
|
|
mrb_obj_iv_set(mrb,
|
|
|
|
mrb_obj_ptr(self),
|
|
|
|
getSym(mrb, iv),
|
|
|
|
propObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
void
|
|
|
|
freeInstance(mrb_state *, void *instance)
|
|
|
|
{
|
|
|
|
delete static_cast<T*>(instance);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline mrb_value
|
|
|
|
mrb_bool_value(bool value)
|
|
|
|
{
|
|
|
|
return value ? mrb_true_value() : mrb_false_value();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
_mrb_bool(mrb_value o)
|
|
|
|
{
|
|
|
|
return mrb_test(o);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class C>
|
|
|
|
inline mrb_value
|
|
|
|
objectLoad(mrb_state *mrb, mrb_value self, const mrb_data_type &type)
|
|
|
|
{
|
|
|
|
RClass *klass = mrb_class_ptr(self);
|
|
|
|
char *data;
|
|
|
|
int data_len;
|
|
|
|
mrb_get_args(mrb, "s", &data, &data_len);
|
|
|
|
|
|
|
|
C *c = C::deserialize(data, data_len);
|
|
|
|
|
2014-08-09 08:38:42 +00:00
|
|
|
RData *obj = mrb_data_object_alloc(mrb, klass, c, &type);
|
|
|
|
mrb_value obj_value = mrb_obj_value(obj);
|
2013-09-01 14:27:21 +00:00
|
|
|
|
|
|
|
return obj_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
MRB_METHOD_PUB(inspectObject);
|
|
|
|
|
|
|
|
#endif // BINDINGUTIL_H
|