Hello!
Today I've added support for functions which return references. This is almost completly transparent ie. you use SH_DECL_HOOK* normally, then you use SH_ADD_HOOK_* normally, etc.
If you want to use it, you only need to download the newest
sourcehook.h from svn.
I've tested it with const and non-const references, many hooks, recalls, even callclasses and META_RESULT_ORIG_RET and META_RESULT_OVERRIDE_RET work (see
testrefret.cpp in svn).
There's one special new thing:
If you want to return MRES_IGNORED or MRES_HANDLED from a hook handler for a function returning a reference, you'd have to use RETURN_META_VALUE normally; the return value gets ignored so you can pass in anything, but you usually don't have a spare variable lying around to return. So you can (=should) use RETURN_META_NOREF instead:
RETURN_META_NOREF(MRES_IGNORED, int&); works like RETURN_META_VALUE but returns some garbage which you don't have to care about
If you're interested in how I implemented all this (you might have heard that I was planning a separate SH_DECL_* macro set; luckily I didn't have to go that far), read sourcehook.hxx around line 307. Actually, if you're too lazy to look it up, I'll copy it here:
Quote:
// How it works:
// SH_SETUPCALLS doesn't use plain rettype to store the temporary return values (plugin ret, orig ret,
// override ret) anymore; instead, it uses SourceHook::ReferenceCarrier<rettype>::type
// this is typedefed to the original rettype normally, but if the rettype is a reference, it's a special class
// which stores the reference as a pointer, and implements constructors, operator= and a conversion operator.
// special cases were needed for getoverrideret / getorigret; these are implemented through the
// SourceHook::MacroRefHelpers structs.
// Furthermore, SetOverrideRet had to be changed a bit; see SourceHook::OverrideFunctor somewhere down in this file.
|
Anyway, maybe you want to see an example:
Code:
struct MyTest
{
int m_Var;
virtual int & Func(int hello)
{
m_Var = hello;
return m_Var;
}
};
int &MyPostHook(int a)
{
static int m_MyVar_ThreeExclamationMarks = 50;
// increment the orig ret twice
META_RESULT_ORIG_RET(int&) += 2;
// override with myvar
RETURN_META_VALUE(MRES_OVERRIDE, m_MyVar_ThreeExclamationMarks);
}
SH_DECL_HOOK1(MyTest, Func, SH_NOATTRIB, 0, int&, int);
void TheTest()
{
MyTest test;
// call through a pointer so that the compiler doesn't remove the virtal function lookup
MyTest *pTest = &test;
int &hello1 = pTest->Func(100);
printf("without hook: test.m_Var is %d --- hello is %d\n", test.m_Var, hello1);
SH_ADD_HOOK_STATICFUNC(MyTest, Func, pTest, MyPostHook, true);
int &hello2 = pTest->Func(100);
printf("with hook: test.m_Var is %d --- hello is %d\n", test.m_Var, hello2);
}
I've just run it and this is the output:
Quote:
without hook: test.m_Var is 100 --- hello is 100
with hook: test.m_Var is 102 --- hello is 50
|
So, as you can see, it seems to work!
What still needs to be done:
-- Someone add it to the wiki XD
So, have fun with it!
PS: I'm leaving for vacation for 2 weeks so if something doesn't work, complain here, I'll fix it when I'm back XD (though I've tested it pretty extensively on both MSVC and GCC). Merci.
__________________