mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-16 01:02:03 +00:00
- Moved all virtual function related template code to its own file because it depends on includes that cannot be done in dobject.h.
This commit is contained in:
parent
14a9c13113
commit
696af7d7e5
9 changed files with 136 additions and 129 deletions
|
@ -1419,10 +1419,6 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VMEXPORT_NATIVES_START(AActor, DThinker)
|
|
||||||
VMEXPORT_NATIVES_FUNC(DropInventory)
|
|
||||||
VMEXPORT_NATIVES_END(AActor)
|
|
||||||
|
|
||||||
class FActorIterator
|
class FActorIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "a_sharedglobal.h"
|
#include "a_sharedglobal.h"
|
||||||
#include "dsectoreffect.h"
|
#include "dsectoreffect.h"
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
|
#include "virtual.h"
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
|
120
src/dobject.h
120
src/dobject.h
|
@ -153,34 +153,6 @@ protected: \
|
||||||
#define HAS_FIELDS \
|
#define HAS_FIELDS \
|
||||||
static void InitNativeFields();
|
static void InitNativeFields();
|
||||||
|
|
||||||
// Templates really are powerful
|
|
||||||
#define VMEXPORTED_NATIVES_START \
|
|
||||||
template<class owner> class ExportedNatives : public ExportedNatives<typename owner::Super> {}; \
|
|
||||||
template<> class ExportedNatives<void> { \
|
|
||||||
protected: ExportedNatives<void>() {} \
|
|
||||||
public: \
|
|
||||||
static ExportedNatives<void> *Get() { static ExportedNatives<void> *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives<void>; return Instance; } \
|
|
||||||
ExportedNatives<void>(const ExportedNatives<void>&) = delete; \
|
|
||||||
ExportedNatives<void>(ExportedNatives<void>&&) = delete;
|
|
||||||
|
|
||||||
#define VMEXPORTED_NATIVES_FUNC(func) \
|
|
||||||
template<class ret, class object, class ... args> ret func(void *ptr, args ... arglist) { return ret(); }
|
|
||||||
|
|
||||||
#define VMEXPORTED_NATIVES_END };
|
|
||||||
|
|
||||||
#define VMEXPORT_NATIVES_START(cls, parent) \
|
|
||||||
template<> class ExportedNatives<cls> : public ExportedNatives<parent> { \
|
|
||||||
protected: ExportedNatives<cls>() {} \
|
|
||||||
public: \
|
|
||||||
static ExportedNatives<cls> *Get() { static ExportedNatives<cls> *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives<cls>; return Instance; } \
|
|
||||||
ExportedNatives<cls>(const ExportedNatives<cls>&) = delete; \
|
|
||||||
ExportedNatives<cls>(ExportedNatives<cls>&&) = delete;
|
|
||||||
|
|
||||||
#define VMEXPORT_NATIVES_FUNC(func) \
|
|
||||||
template<class ret, class object, class ... args> ret func(void *ptr, args ... arglist) { return static_cast<object *>(ptr)->object::func(arglist...); }
|
|
||||||
|
|
||||||
#define VMEXPORT_NATIVES_END(cls) };
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
# pragma section(".creg$u",read)
|
# pragma section(".creg$u",read)
|
||||||
# define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) ClassReg * const cls::RegistrationInfoPtr = &cls::RegistrationInfo;
|
# define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) ClassReg * const cls::RegistrationInfoPtr = &cls::RegistrationInfo;
|
||||||
|
@ -615,100 +587,8 @@ protected:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//Initial list
|
|
||||||
VMEXPORTED_NATIVES_START
|
|
||||||
VMEXPORTED_NATIVES_FUNC(Destroy)
|
|
||||||
VMEXPORTED_NATIVES_FUNC(Tick)
|
|
||||||
VMEXPORTED_NATIVES_FUNC(DropInventory)
|
|
||||||
VMEXPORTED_NATIVES_END
|
|
||||||
|
|
||||||
class AInventory;//
|
class AInventory;//
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class DVMObject : public T
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static char *FormatClassName()
|
|
||||||
{
|
|
||||||
static char *name = nullptr;
|
|
||||||
if (name == nullptr)
|
|
||||||
{
|
|
||||||
name = new char[64];
|
|
||||||
mysnprintf(name, 64, "DVMObject<%s>", Super::RegistrationInfo.Name);
|
|
||||||
atterm([]{ delete[] DVMObject<T>::RegistrationInfo.Name; });
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual PClass *StaticType() const
|
|
||||||
{
|
|
||||||
return RegistrationInfo.MyClass;
|
|
||||||
}
|
|
||||||
static ClassReg RegistrationInfo;
|
|
||||||
static ClassReg * const RegistrationInfoPtr;
|
|
||||||
typedef T Super;
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef DVMObject<T> ThisClass;
|
|
||||||
static void InPlaceConstructor(void *mem)
|
|
||||||
{
|
|
||||||
new((EInPlace *)mem) DVMObject<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
void Destroy()
|
|
||||||
{
|
|
||||||
if (ObjectFlags & OF_SuperCall)
|
|
||||||
{
|
|
||||||
ObjectFlags &= OF_SuperCall;
|
|
||||||
ExportedNatives<T>::Get()->template Destroy<void, T>(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static int VIndex = -1;
|
|
||||||
if (VIndex < 0)
|
|
||||||
{
|
|
||||||
// Look up the virtual function index in the defining class because this may have gotten overloaded in subclasses with something different than a virtual override.
|
|
||||||
auto sym = dyn_cast<PFunction>(RUNTIME_CLASS(DObject)->Symbols.FindSymbol("Destroy", false));
|
|
||||||
assert(sym != nullptr);
|
|
||||||
VIndex = sym->Variants[0].Implementation->VirtualIndex;
|
|
||||||
assert(VIndex >= 0);
|
|
||||||
}
|
|
||||||
// Without the type cast this picks the 'void *' assignment...
|
|
||||||
VMValue params[1] = { (DObject*)this };
|
|
||||||
VMFrameStack stack;
|
|
||||||
stack.Call(GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Tick()
|
|
||||||
{
|
|
||||||
ExportedNatives<T>::Get()->template Tick<void, T>(this);
|
|
||||||
}
|
|
||||||
AInventory *DropInventory(AInventory *item)
|
|
||||||
{
|
|
||||||
return ExportedNatives<T>::Get()->template DropInventory<AInventory *, T>(this, item);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
ClassReg DVMObject<T>::RegistrationInfo =
|
|
||||||
{
|
|
||||||
nullptr,
|
|
||||||
DVMObject<T>::FormatClassName(),
|
|
||||||
&DVMObject<T>::Super::RegistrationInfo,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
DVMObject<T>::InPlaceConstructor,
|
|
||||||
nullptr,
|
|
||||||
sizeof(DVMObject<T>),
|
|
||||||
DVMObject<T>::MetaClassNum
|
|
||||||
};
|
|
||||||
template<class T> _DECLARE_TI(DVMObject<T>)
|
|
||||||
|
|
||||||
VMEXPORT_NATIVES_START(DObject, void)
|
|
||||||
VMEXPORT_NATIVES_FUNC(Destroy)
|
|
||||||
VMEXPORT_NATIVES_END(DObject)
|
|
||||||
|
|
||||||
// When you write to a pointer to an Object, you must call this for
|
// When you write to a pointer to an Object, you must call this for
|
||||||
// proper bookkeeping in case the Object holding this pointer has
|
// proper bookkeeping in case the Object holding this pointer has
|
||||||
// already been processed by the GC.
|
// already been processed by the GC.
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
#include "d_player.h"
|
#include "d_player.h"
|
||||||
|
#include "virtual.h"
|
||||||
|
|
||||||
|
|
||||||
static cycle_t ThinkCycles;
|
static cycle_t ThinkCycles;
|
||||||
|
|
|
@ -108,10 +108,6 @@ private:
|
||||||
DThinker *NextThinker, *PrevThinker;
|
DThinker *NextThinker, *PrevThinker;
|
||||||
};
|
};
|
||||||
|
|
||||||
VMEXPORT_NATIVES_START(DThinker, DObject)
|
|
||||||
VMEXPORT_NATIVES_FUNC(Tick)
|
|
||||||
VMEXPORT_NATIVES_END(DThinker)
|
|
||||||
|
|
||||||
class FThinkerIterator
|
class FThinkerIterator
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "a_hereticartifacts.cpp"
|
#include "a_hereticartifacts.cpp"
|
||||||
#include "a_hereticweaps.cpp"
|
#include "a_hereticweaps.cpp"
|
||||||
#include "a_ironlich.cpp"
|
#include "a_ironlich.cpp"
|
||||||
#include "a_wizard.cpp"
|
|
||||||
|
|
||||||
|
|
||||||
static FRandom pr_podpain ("PodPain");
|
static FRandom pr_podpain ("PodPain");
|
||||||
|
|
|
@ -72,6 +72,7 @@
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
#include "r_utility.h"
|
#include "r_utility.h"
|
||||||
#include "thingdef.h"
|
#include "thingdef.h"
|
||||||
|
#include "virtual.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
#include "p_blockmap.h"
|
#include "p_blockmap.h"
|
||||||
#include "a_morph.h"
|
#include "a_morph.h"
|
||||||
#include "p_spec.h"
|
#include "p_spec.h"
|
||||||
|
#include "virtual.h"
|
||||||
|
|
||||||
static FRandom pr_skullpop ("SkullPop");
|
static FRandom pr_skullpop ("SkullPop");
|
||||||
|
|
||||||
|
|
132
src/virtual.h
Normal file
132
src/virtual.h
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Templates really are powerful
|
||||||
|
#define VMEXPORTED_NATIVES_START \
|
||||||
|
template<class owner> class ExportedNatives : public ExportedNatives<typename owner::Super> {}; \
|
||||||
|
template<> class ExportedNatives<void> { \
|
||||||
|
protected: ExportedNatives<void>() {} \
|
||||||
|
public: \
|
||||||
|
static ExportedNatives<void> *Get() { static ExportedNatives<void> *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives<void>; return Instance; } \
|
||||||
|
ExportedNatives<void>(const ExportedNatives<void>&) = delete; \
|
||||||
|
ExportedNatives<void>(ExportedNatives<void>&&) = delete;
|
||||||
|
|
||||||
|
#define VMEXPORTED_NATIVES_FUNC(func) \
|
||||||
|
template<class ret, class object, class ... args> ret func(void *ptr, args ... arglist) { return ret(); }
|
||||||
|
|
||||||
|
#define VMEXPORTED_NATIVES_END };
|
||||||
|
|
||||||
|
#define VMEXPORT_NATIVES_START(cls, parent) \
|
||||||
|
template<> class ExportedNatives<cls> : public ExportedNatives<parent> { \
|
||||||
|
protected: ExportedNatives<cls>() {} \
|
||||||
|
public: \
|
||||||
|
static ExportedNatives<cls> *Get() { static ExportedNatives<cls> *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives<cls>; return Instance; } \
|
||||||
|
ExportedNatives<cls>(const ExportedNatives<cls>&) = delete; \
|
||||||
|
ExportedNatives<cls>(ExportedNatives<cls>&&) = delete;
|
||||||
|
|
||||||
|
#define VMEXPORT_NATIVES_FUNC(func) \
|
||||||
|
template<class ret, class object, class ... args> ret func(void *ptr, args ... arglist) { return static_cast<object *>(ptr)->object::func(arglist...); }
|
||||||
|
|
||||||
|
#define VMEXPORT_NATIVES_END(cls) };
|
||||||
|
|
||||||
|
|
||||||
|
//Initial list
|
||||||
|
VMEXPORTED_NATIVES_START
|
||||||
|
VMEXPORTED_NATIVES_FUNC(Destroy)
|
||||||
|
VMEXPORTED_NATIVES_FUNC(Tick)
|
||||||
|
VMEXPORTED_NATIVES_FUNC(DropInventory)
|
||||||
|
VMEXPORTED_NATIVES_END
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class DVMObject : public T
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static char *FormatClassName()
|
||||||
|
{
|
||||||
|
static char *name = nullptr;
|
||||||
|
if (name == nullptr)
|
||||||
|
{
|
||||||
|
name = new char[64];
|
||||||
|
mysnprintf(name, 64, "DVMObject<%s>", Super::RegistrationInfo.Name);
|
||||||
|
atterm([]{ delete[] DVMObject<T>::RegistrationInfo.Name; });
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual PClass *StaticType() const
|
||||||
|
{
|
||||||
|
return RegistrationInfo.MyClass;
|
||||||
|
}
|
||||||
|
static ClassReg RegistrationInfo;
|
||||||
|
static ClassReg * const RegistrationInfoPtr;
|
||||||
|
typedef T Super;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef DVMObject<T> ThisClass;
|
||||||
|
static void InPlaceConstructor(void *mem)
|
||||||
|
{
|
||||||
|
new((EInPlace *)mem) DVMObject<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Destroy()
|
||||||
|
{
|
||||||
|
if (ObjectFlags & OF_SuperCall)
|
||||||
|
{
|
||||||
|
ObjectFlags &= OF_SuperCall;
|
||||||
|
ExportedNatives<T>::Get()->template Destroy<void, T>(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static int VIndex = -1;
|
||||||
|
if (VIndex < 0)
|
||||||
|
{
|
||||||
|
// Look up the virtual function index in the defining class because this may have gotten overloaded in subclasses with something different than a virtual override.
|
||||||
|
auto sym = dyn_cast<PFunction>(RUNTIME_CLASS(DObject)->Symbols.FindSymbol("Destroy", false));
|
||||||
|
assert(sym != nullptr);
|
||||||
|
VIndex = sym->Variants[0].Implementation->VirtualIndex;
|
||||||
|
assert(VIndex >= 0);
|
||||||
|
}
|
||||||
|
// Without the type cast this picks the 'void *' assignment...
|
||||||
|
VMValue params[1] = { (DObject*)this };
|
||||||
|
VMFrameStack stack;
|
||||||
|
stack.Call(GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Tick()
|
||||||
|
{
|
||||||
|
ExportedNatives<T>::Get()->template Tick<void, T>(this);
|
||||||
|
}
|
||||||
|
AInventory *DropInventory(AInventory *item)
|
||||||
|
{
|
||||||
|
return ExportedNatives<T>::Get()->template DropInventory<AInventory *, T>(this, item);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
ClassReg DVMObject<T>::RegistrationInfo =
|
||||||
|
{
|
||||||
|
nullptr,
|
||||||
|
DVMObject<T>::FormatClassName(),
|
||||||
|
&DVMObject<T>::Super::RegistrationInfo,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
DVMObject<T>::InPlaceConstructor,
|
||||||
|
nullptr,
|
||||||
|
sizeof(DVMObject<T>),
|
||||||
|
DVMObject<T>::MetaClassNum
|
||||||
|
};
|
||||||
|
template<class T> _DECLARE_TI(DVMObject<T>)
|
||||||
|
|
||||||
|
VMEXPORT_NATIVES_START(DObject, void)
|
||||||
|
VMEXPORT_NATIVES_FUNC(Destroy)
|
||||||
|
VMEXPORT_NATIVES_END(DObject)
|
||||||
|
|
||||||
|
VMEXPORT_NATIVES_START(DThinker, DObject)
|
||||||
|
VMEXPORT_NATIVES_FUNC(Tick)
|
||||||
|
VMEXPORT_NATIVES_END(DThinker)
|
||||||
|
|
||||||
|
VMEXPORT_NATIVES_START(AActor, DThinker)
|
||||||
|
VMEXPORT_NATIVES_FUNC(DropInventory)
|
||||||
|
VMEXPORT_NATIVES_END(AActor)
|
||||||
|
|
Loading…
Reference in a new issue