|
|
|
@ -87,7 +87,8 @@ namespace DFHack
|
|
|
|
|
with code defined by DFHack, while retaining ability to
|
|
|
|
|
call the original code. The API can be safely used from
|
|
|
|
|
plugins, and multiple hooks for the same vmethod are
|
|
|
|
|
automatically chained in undefined order.
|
|
|
|
|
automatically chained (subclass before superclass; at same
|
|
|
|
|
level highest priority called first; undefined order otherwise).
|
|
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
|
|
|
|
|
@ -105,6 +106,8 @@ namespace DFHack
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE(my_hack, foo);
|
|
|
|
|
or
|
|
|
|
|
IMPLEMENT_VMETHOD_INTERPOSE_PRIO(my_hack, foo, priority);
|
|
|
|
|
|
|
|
|
|
void init() {
|
|
|
|
|
if (!INTERPOSE_HOOK(my_hack, foo).apply())
|
|
|
|
@ -121,9 +124,11 @@ namespace DFHack
|
|
|
|
|
static DFHack::VMethodInterposeLink<interpose_base,interpose_ptr_##name> interpose_##name; \
|
|
|
|
|
rtype interpose_fn_##name args
|
|
|
|
|
|
|
|
|
|
#define IMPLEMENT_VMETHOD_INTERPOSE(class,name) \
|
|
|
|
|
#define IMPLEMENT_VMETHOD_INTERPOSE_PRIO(class,name,priority) \
|
|
|
|
|
DFHack::VMethodInterposeLink<class::interpose_base,class::interpose_ptr_##name> \
|
|
|
|
|
class::interpose_##name(&class::interpose_base::name, &class::interpose_fn_##name);
|
|
|
|
|
class::interpose_##name(&class::interpose_base::name, &class::interpose_fn_##name, priority);
|
|
|
|
|
|
|
|
|
|
#define IMPLEMENT_VMETHOD_INTERPOSE(class,name) IMPLEMENT_VMETHOD_INTERPOSE_PRIO(class,name,0)
|
|
|
|
|
|
|
|
|
|
#define INTERPOSE_NEXT(name) (this->*interpose_##name.chain)
|
|
|
|
|
#define INTERPOSE_HOOK(class, name) (class::interpose_##name)
|
|
|
|
@ -140,6 +145,7 @@ namespace DFHack
|
|
|
|
|
int vmethod_idx;
|
|
|
|
|
void *interpose_method; // Pointer to the code of the interposing method
|
|
|
|
|
void *chain_mptr; // Pointer to the chain field below
|
|
|
|
|
int priority;
|
|
|
|
|
|
|
|
|
|
bool applied;
|
|
|
|
|
void *saved_chain; // Previous pointer to the code
|
|
|
|
@ -155,7 +161,7 @@ namespace DFHack
|
|
|
|
|
VMethodInterposeLinkBase *get_first_interpose(virtual_identity *id);
|
|
|
|
|
void find_child_hosts(virtual_identity *cur, void *vmptr);
|
|
|
|
|
public:
|
|
|
|
|
VMethodInterposeLinkBase(virtual_identity *host, int vmethod_idx, void *interpose_method, void *chain_mptr);
|
|
|
|
|
VMethodInterposeLinkBase(virtual_identity *host, int vmethod_idx, void *interpose_method, void *chain_mptr, int priority);
|
|
|
|
|
~VMethodInterposeLinkBase();
|
|
|
|
|
|
|
|
|
|
bool is_applied() { return applied; }
|
|
|
|
@ -171,12 +177,13 @@ namespace DFHack
|
|
|
|
|
operator Ptr () { return chain; }
|
|
|
|
|
|
|
|
|
|
template<class Ptr2>
|
|
|
|
|
VMethodInterposeLink(Ptr target, Ptr2 src)
|
|
|
|
|
VMethodInterposeLink(Ptr target, Ptr2 src, int priority)
|
|
|
|
|
: VMethodInterposeLinkBase(
|
|
|
|
|
&Base::_identity,
|
|
|
|
|
vmethod_pointer_to_idx(target),
|
|
|
|
|
method_pointer_to_addr(src),
|
|
|
|
|
&chain
|
|
|
|
|
&chain,
|
|
|
|
|
priority
|
|
|
|
|
)
|
|
|
|
|
{ src = target; /* check compatibility */ }
|
|
|
|
|
};
|
|
|
|
|