290 lines
8.6 KiB
C++
290 lines
8.6 KiB
C++
#ifndef INCLUDED_HX_SCRIPTABLE
|
|
#define INCLUDED_HX_SCRIPTABLE
|
|
|
|
#include <typeinfo>
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic ignored "-Winvalid-offsetof"
|
|
#endif
|
|
|
|
|
|
namespace hx
|
|
{
|
|
|
|
extern bool gEnableJit;
|
|
inline void EnableJit(bool inEnable) { gEnableJit = inEnable; }
|
|
|
|
#define HXCPP_CPPIA_SUPER_ARG(x) , (x)
|
|
|
|
struct ScriptNamedFunction : public ScriptFunction
|
|
{
|
|
ScriptNamedFunction(const ScriptFunction &s) : ScriptFunction(s), name(0), isStatic(false), superExecute(0) { }
|
|
|
|
ScriptNamedFunction(const char *inName=0,StackExecute inExe=0,const char *inSig=0, bool inIsStatic=false, StackExecute superExecute=0)
|
|
: ScriptFunction(inExe, inSig), name(inName), isStatic(inIsStatic), superExecute(superExecute) { }
|
|
|
|
const char *name;
|
|
bool isStatic;
|
|
StackExecute superExecute;
|
|
};
|
|
|
|
|
|
inline void SetFloatAligned(void *inPtr, const Float &inValue)
|
|
{
|
|
#ifdef HXCPP_ALIGN_FLOAT
|
|
int *dest = (int *)inPtr;
|
|
const int *src = (const int *)&inValue;
|
|
dest[1] = src[1];
|
|
#else
|
|
*(Float *)inPtr = inValue;
|
|
#endif
|
|
}
|
|
|
|
|
|
inline Float GetFloatAligned(const void *inPtr)
|
|
{
|
|
#ifdef HXCPP_ALIGN_FLOAT
|
|
Float result;
|
|
int *dest = (int *)&result;
|
|
const int *src = (const int *)inPtr;
|
|
dest[0] = src[0];
|
|
dest[1] = src[1];
|
|
return result;
|
|
#else
|
|
return *(Float *)inPtr;
|
|
#endif
|
|
}
|
|
|
|
|
|
inline void StackContext::pushFloat(Float f)
|
|
{
|
|
SetFloatAligned(pointer, f);
|
|
pointer += sizeof(Float);
|
|
}
|
|
inline void StackContext::pushString(const String &s)
|
|
{
|
|
*(String *)pointer = s;
|
|
pointer += sizeof(String);
|
|
}
|
|
|
|
inline void StackContext::pushObject(Dynamic d)
|
|
{
|
|
*(hx::Object **)pointer = d.mPtr;
|
|
pointer += sizeof(hx::Object *);
|
|
}
|
|
|
|
inline void StackContext::returnFloat(Float f)
|
|
{
|
|
SetFloatAligned(frame, f);
|
|
}
|
|
inline void StackContext::returnString(const String &s)
|
|
{
|
|
*(String *)frame = s;
|
|
}
|
|
inline void StackContext::returnObject(Dynamic d)
|
|
{
|
|
*(hx::Object **)frame = d.mPtr;
|
|
}
|
|
|
|
inline hx::Object *StackContext::getThis(bool inCheckPtr)
|
|
{
|
|
#ifdef HXCPP_CHECK_POINTER
|
|
if (inCheckPtr)
|
|
{
|
|
if (!*(hx::Object **)frame) NullReference("This", false);
|
|
#ifdef HXCPP_GC_CHECK_POINTER
|
|
GCCheckPointer(*(hx::Object **)frame);
|
|
#endif
|
|
}
|
|
#endif
|
|
return *(hx::Object **)frame;
|
|
}
|
|
|
|
|
|
inline Float StackContext::getFloat(int inPos)
|
|
{
|
|
return GetFloatAligned(frame+inPos);
|
|
}
|
|
inline String StackContext::getString(int inPos)
|
|
{
|
|
return *(String *)(frame+inPos);
|
|
}
|
|
inline Dynamic StackContext::getObject(int inPos)
|
|
{
|
|
return *(hx::Object **)(frame+inPos);
|
|
}
|
|
|
|
|
|
enum SignatureChar
|
|
{
|
|
sigVoid = 'v',
|
|
sigBool = 'b',
|
|
sigInt = 'i',
|
|
sigFloat = 'f',
|
|
sigString = 's',
|
|
sigObject = 'o',
|
|
};
|
|
|
|
|
|
|
|
struct AutoStack
|
|
{
|
|
CppiaCtx *ctx;
|
|
unsigned char *pointer;
|
|
unsigned char *frame;
|
|
|
|
AutoStack(CppiaCtx *inCtx) : ctx(inCtx)
|
|
{
|
|
frame = ctx->frame;
|
|
pointer = ctx->pointer;
|
|
ctx->frame = pointer;
|
|
}
|
|
AutoStack(CppiaCtx *inCtx,unsigned char *inPointer) : ctx(inCtx)
|
|
{
|
|
frame = ctx->frame;
|
|
pointer = inPointer;
|
|
ctx->frame = pointer;
|
|
}
|
|
|
|
~AutoStack()
|
|
{
|
|
ctx->pointer = pointer;
|
|
ctx->frame = frame;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
typedef hx::Object * (*ScriptableClassFactory)(void **inVTable,int inDataSize);
|
|
typedef hx::Object * (*ScriptableInterfaceFactory)(void **inVTable,::hx::Object *);
|
|
|
|
void ScriptableRegisterClass( String inName, int inBaseSize, ScriptNamedFunction *inFunctions, ScriptableClassFactory inFactory, ScriptFunction inConstruct);
|
|
|
|
|
|
#if (HXCPP_API_LEVEL >= 330)
|
|
void ScriptableRegisterInterface( String inName, ScriptNamedFunction *inFunctions, void *inInterfacePointers);
|
|
void ScriptableRegisterNameSlots(const char *inNames[], int inLength);
|
|
|
|
#else
|
|
void ScriptableRegisterInterface( String inName, ScriptNamedFunction *inFunctions,const hx::type_info *inType, ScriptableInterfaceFactory inFactory);
|
|
#endif
|
|
|
|
::String ScriptableToString(void *);
|
|
hx::Class ScriptableGetClass(void *);
|
|
int ScriptableGetType(void *);
|
|
void ScriptableMark(void *, hx::Object *, HX_MARK_PARAMS);
|
|
void ScriptableVisit(void *, hx::Object *, HX_VISIT_PARAMS);
|
|
bool ScriptableField(hx::Object *, const ::String &,hx::PropertyAccess inCallProp,Dynamic &outResult);
|
|
bool ScriptableField(hx::Object *, int inName,hx::PropertyAccess inCallProp,Float &outResult);
|
|
bool ScriptableField(hx::Object *, int inName,hx::PropertyAccess inCallProp,Dynamic &outResult);
|
|
void ScriptableGetFields(hx::Object *inObject, Array< ::String> &outFields);
|
|
bool ScriptableSetField(hx::Object *, const ::String &, Dynamic inValue,hx::PropertyAccess inCallProp, Dynamic &outValue);
|
|
|
|
|
|
class CppiaLoadedModule_obj : public ::hx::Object
|
|
{
|
|
public:
|
|
virtual void run() = 0;
|
|
virtual void boot() = 0;
|
|
virtual ::hx::Class resolveClass( ::String inName) = 0;
|
|
};
|
|
typedef ::hx::ObjectPtr<CppiaLoadedModule_obj> CppiaLoadedModule;
|
|
|
|
|
|
|
|
} // End namespace hx
|
|
|
|
void __scriptable_load_neko(String inName);
|
|
void __scriptable_load_cppia(String inCode);
|
|
::hx::CppiaLoadedModule __scriptable_cppia_from_string(String inCode);
|
|
::hx::CppiaLoadedModule __scriptable_cppia_from_data(Array<unsigned char> inBytes);
|
|
void __scriptable_load_neko_bytes(Array<unsigned char> inBytes);
|
|
void __scriptable_load_abc(Array<unsigned char> inBytes);
|
|
|
|
#if (HXCPP_API_LEVEL >= 330)
|
|
|
|
#define HX_SCRIPTABLE_REGISTER_INTERFACE(name,class) \
|
|
hx::ScriptableRegisterInterface( HX_CSTRING(name), __scriptableFunctions, & class##_scriptable )
|
|
|
|
#else
|
|
|
|
#define HX_SCRIPTABLE_REGISTER_INTERFACE(name,class) \
|
|
hx::ScriptableRegisterInterface( HX_CSTRING(name), __scriptableFunctions, &typeid(class), class##__scriptable::__script_create )
|
|
|
|
#endif
|
|
|
|
#define HX_SCRIPTABLE_REGISTER_CLASS(name,class) \
|
|
hx::ScriptableRegisterClass( HX_CSTRING(name), (int)offsetof(class##__scriptable,__scriptVTable) + sizeof(void *), __scriptableFunctions, class##__scriptable::__script_create, class##__scriptable::__script_construct )
|
|
|
|
|
|
#ifdef HXCPP_VISIT_ALLOCS
|
|
#define SCRIPTABLE_VISIT_FUNCTION \
|
|
void __Visit(HX_VISIT_PARAMS) { super::__Visit(HX_VISIT_ARG); hx::ScriptableVisit(__scriptVTable[-1],this,HX_VISIT_ARG); }
|
|
#else
|
|
#define SCRIPTABLE_VISIT_FUNCTION
|
|
#endif
|
|
|
|
|
|
#define HX_DEFINE_SCRIPTABLE(ARG_LIST) \
|
|
inline void *operator new( size_t inSize, int inExtraDataSize ) \
|
|
{ \
|
|
return hx::InternalNew(inSize + inExtraDataSize,true); \
|
|
} \
|
|
inline void operator delete(void *,int) {} \
|
|
public: \
|
|
void **__scriptVTable; \
|
|
static hx::Object *__script_create(void **inVTable, int inExtra) { \
|
|
__ME *result = new (inExtra) __ME(); \
|
|
result->__scriptVTable = inVTable; \
|
|
return result; } \
|
|
void ** __GetScriptVTable() { return __scriptVTable; } \
|
|
::String toString() { if (__scriptVTable[0] ) \
|
|
{ hx::CppiaCtx *ctx = hx::CppiaCtx::getCurrent(); hx::AutoStack a(ctx); ctx->pushObject(this); return ctx->runString(__scriptVTable[0]); } \
|
|
else return __superString::toString(); } \
|
|
::String __ToString() const { return hx::ScriptableToString(__scriptVTable[-1]); } \
|
|
hx::Class __GetClass() const { return hx::ScriptableGetClass(__scriptVTable[-1]); } \
|
|
int __GetType() const { return hx::ScriptableGetType(__scriptVTable[-1]); } \
|
|
void __Mark(HX_MARK_PARAMS) { super::__Mark(HX_MARK_ARG); hx::ScriptableMark(__scriptVTable[-1],this,HX_MARK_ARG); } \
|
|
SCRIPTABLE_VISIT_FUNCTION
|
|
|
|
|
|
|
|
#define HX_DEFINE_SCRIPTABLE_INTERFACE \
|
|
void **__scriptVTable; \
|
|
Dynamic mDelegate; \
|
|
hx::Object *__GetRealObject() { return mDelegate.mPtr; } \
|
|
SCRIPTABLE_VISIT_FUNCTION \
|
|
void ** __GetScriptVTable() { return __scriptVTable; } \
|
|
public: \
|
|
static hx::Object *__script_create(void **inVTable,hx::Object *inDelegate) { \
|
|
__ME *result = new __ME(); \
|
|
result->__scriptVTable = inVTable; \
|
|
result->mDelegate = inDelegate; \
|
|
return result; }
|
|
|
|
|
|
|
|
#define HX_DEFINE_SCRIPTABLE_DYNAMIC \
|
|
\
|
|
hx::Val __Field(const ::String &inName,hx::PropertyAccess inCallProp) \
|
|
{ Dynamic result; if (hx::ScriptableField(this,inName,inCallProp,result)) return result; return super::__Field(inName,inCallProp); } \
|
|
Float __INumField(int inFieldID) \
|
|
{ Float result; if (hx::ScriptableField(this,inFieldID,hx::paccAlways,result)) return result; return super::__INumField(inFieldID); } \
|
|
Dynamic __IField(int inFieldID) \
|
|
{ Dynamic result; if (hx::ScriptableField(this,inFieldID,hx::paccAlways,result)) return result; return super::__IField(inFieldID); } \
|
|
hx::Val __SetField(const ::String &inName,const hx::Val &inValue,hx::PropertyAccess inCallProp) \
|
|
{ \
|
|
Dynamic value; \
|
|
if (hx::ScriptableSetField(this, inName, inValue,inCallProp,value)) \
|
|
return value; \
|
|
return super::__SetField(inName,inValue,inCallProp); \
|
|
} \
|
|
void __GetFields(Array< ::String> &outFields) \
|
|
{ super::__GetFields(outFields); hx::ScriptableGetFields(this,outFields); }
|
|
|
|
|
|
|
|
|
|
#endif
|