1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2024-12-10 22:24:12 +01:00

ForcedByRef works; next step will be: returns!

--HG--
branch : hookman_autogen
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/branches/hookman_autogen%40548
This commit is contained in:
Pavol Marko 2007-11-07 16:56:03 +00:00
parent 94223941d2
commit d4bd0261f1
5 changed files with 142 additions and 68 deletions

View File

@ -196,6 +196,39 @@ namespace SourceHook
IA32_Pop_Reg(&m_HookFunc, REG_EDI); IA32_Pop_Reg(&m_HookFunc, REG_EDI);
} }
short GenContext::GetParamsStackSize()
{
short acc = 0;
for (int i = 0; i < m_Proto.GetNumOfParams(); ++i)
{
acc += GetStackSize(m_Proto.GetParam(i));
}
// Memory return: address is first param
if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem)
acc += SIZE_PTR;
// :TODO: cdecl: THIS POINTER AS FIRST PARAM!!!
return acc;
}
short GenContext::GetForcedByRefParamOffset(int p)
{
short off = 0;
for (int i = 0; i < p; ++i)
{
if (m_Proto.GetParam(i).flags & PassFlag_ForcedByRef)
off += GetStackSize(m_Proto.GetParam(i));
}
return off;
}
short GenContext::GetForcedByRefParamsSize()
{
return GetForcedByRefParamOffset(m_Proto.GetNumOfParams());
}
jit_int32_t GenContext::PushRef(jit_int32_t param_offset, const IntPassInfo &pi) jit_int32_t GenContext::PushRef(jit_int32_t param_offset, const IntPassInfo &pi)
{ {
// push [ebp+<offset>] // push [ebp+<offset>]
@ -282,23 +315,31 @@ namespace SourceHook
} }
} }
jit_int32_t GenContext::PushObject(jit_int32_t param_offset, const IntPassInfo &pi) jit_int32_t GenContext::PushObject(jit_int32_t param_offset, const IntPassInfo &pi, jit_int32_t place_fbrr)
{
if ((pi.flags & PassFlag_ForcedByRef) == 0)
{ {
// make room on the stack // make room on the stack
// sub esp, <size> // sub esp, <size>
IA32_Sub_Rm_ImmAuto(&m_HookFunc, REG_ESP, GetStackSize(pi), MOD_REG); IA32_Sub_Rm_ImmAuto(&m_HookFunc, REG_ESP, GetStackSize(pi), MOD_REG);
}
// if there is a copy constructor.. // if there is a copy constructor..
if (pi.pCopyCtor) if (pi.pCopyCtor)
{ {
// save eax // save eax
// push src addr // push src addr
// this= target addr = esp+12 // this= target addr = forcedbyref ? ebp+place_fbrr : esp+12
// call copy constructor // call copy constructor
// restore eax // restore eax
IA32_Push_Reg(&m_HookFunc, REG_EAX); IA32_Push_Reg(&m_HookFunc, REG_EAX);
if (pi.flags & PassFlag_ForcedByRef)
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, place_fbrr);
else
IA32_Lea_Reg_DispRegMultImm8(&m_HookFunc, REG_ECX, REG_NOIDX, REG_ESP, NOSCALE, 4); IA32_Lea_Reg_DispRegMultImm8(&m_HookFunc, REG_ECX, REG_NOIDX, REG_ESP, NOSCALE, 4);
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EAX, REG_EBP, param_offset); IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EAX, REG_EBP, param_offset);
IA32_Push_Reg(&m_HookFunc, REG_EAX); IA32_Push_Reg(&m_HookFunc, REG_EAX);
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
@ -314,19 +355,50 @@ namespace SourceHook
BitwiseCopy_Setup(); BitwiseCopy_Setup();
//lea edi, [esp+8] //if forcedbyref:
// lea edi, [ebp_place_fbrr]
//else
// lea edi, [esp+8] - bc_setup pushed two regs onto the stack!
//lea esi, [ebp+<offs>] //lea esi, [ebp+<offs>]
if (pi.flags & PassFlag_ForcedByRef)
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDI, REG_EBP, place_fbrr);
else
IA32_Lea_Reg_DispRegMultImm8(&m_HookFunc, REG_EDI, REG_NOIDX, REG_ESP, NOSCALE, 8); IA32_Lea_Reg_DispRegMultImm8(&m_HookFunc, REG_EDI, REG_NOIDX, REG_ESP, NOSCALE, 8);
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ESI, REG_EBP, param_offset); IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ESI, REG_EBP, param_offset);
BitwiseCopy_Do(pi.size); BitwiseCopy_Do(pi.size);
} }
// forcedref: push reference to ebp+place_fbrr
if (pi.flags & PassFlag_ForcedByRef)
{
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, place_fbrr);
IA32_Push_Reg(&m_HookFunc, REG_ECX);
return SIZE_PTR;
}
return DownCastSize(pi.size); return DownCastSize(pi.size);
} }
void GenContext::DestroyParams(jit_int32_t fbrr_base)
{
for (int i = m_Proto.GetNumOfParams() - 1; i >= 0; --i)
{
const IntPassInfo &pi = m_Proto.GetParam(i);
if (pi.type == PassInfo::PassType_Object && (pi.flags & PassInfo::PassFlag_ODtor) &&
(pi.flags & PassInfo::PassFlag_ByVal) && (pi.flags & PassFlag_ForcedByRef))
{
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, fbrr_base + GetForcedByRefParamOffset(i));
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(pi.pDtor));
IA32_Call_Reg(&m_HookFunc, REG_EAX);
}
}
}
// May not touch eax! // May not touch eax!
jit_int32_t GenContext::PushParams(jit_int32_t param_base_offset, jit_int32_t save_ret_to, int v_place_for_memret) jit_int32_t GenContext::PushParams(jit_int32_t param_base_offset, jit_int32_t save_ret_to, int v_place_for_memret,
jit_int32_t v_place_fbrr_base)
{ {
jit_int32_t added_to_stack = 0; jit_int32_t added_to_stack = 0;
jit_int32_t ret = 0; jit_int32_t ret = 0;
@ -354,7 +426,7 @@ namespace SourceHook
ret = PushFloat(cur_offset, pi); ret = PushFloat(cur_offset, pi);
break; break;
case PassInfo::PassType_Object: case PassInfo::PassType_Object:
ret = PushObject(cur_offset, pi); ret = PushObject(cur_offset, pi, v_place_fbrr_base + GetForcedByRefParamOffset(i));
break; break;
} }
} }
@ -768,7 +840,7 @@ namespace SourceHook
} }
void GenContext::GenerateCallHooks(int v_status, int v_prev_res, int v_cur_res, int v_iter, void GenContext::GenerateCallHooks(int v_status, int v_prev_res, int v_cur_res, int v_iter,
int v_pContext, int base_param_offset, int v_plugin_ret, int v_place_for_memret) int v_pContext, int base_param_offset, int v_plugin_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base)
{ {
jitoffs_t counter, tmppos; jitoffs_t counter, tmppos;
jitoffs_t counter2, tmppos2; jitoffs_t counter2, tmppos2;
@ -815,7 +887,7 @@ namespace SourceHook
// call eax // call eax
// gcc: clean up // gcc: clean up
jit_int32_t gcc_clean_bytes = PushParams(base_param_offset, v_plugin_ret, v_place_for_memret); jit_int32_t gcc_clean_bytes = PushParams(base_param_offset, v_plugin_ret, v_place_for_memret, v_place_fbrr_base);
IA32_Mov_Reg_Rm(&m_HookFunc, REG_ECX, REG_EAX, MOD_REG); IA32_Mov_Reg_Rm(&m_HookFunc, REG_ECX, REG_EAX, MOD_REG);
GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX));
@ -823,11 +895,16 @@ namespace SourceHook
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EAX, 2*SIZE_PTR); IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EAX, 2*SIZE_PTR);
IA32_Call_Reg(&m_HookFunc, REG_EAX); IA32_Call_Reg(&m_HookFunc, REG_EAX);
DestroyParams(v_place_fbrr_base);
SaveRetVal(v_plugin_ret, v_place_for_memret); SaveRetVal(v_plugin_ret, v_place_for_memret);
// cleanup // cleanup
#if SH_COMP == SH_COMP_GCC
IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, gcc_clean_bytes + SIZE_PTR, MOD_REG);
#endif
// params + thisptr // params + thisptr
GCC_ONLY(IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, gcc_clean_bytes + SIZE_PTR, MOD_REG));
// process meta return: // process meta return:
// prev_res = cur_res // prev_res = cur_res
@ -866,25 +943,8 @@ namespace SourceHook
m_HookFunc.rewrite(tmppos, static_cast<jit_int32_t>(counter)); m_HookFunc.rewrite(tmppos, static_cast<jit_int32_t>(counter));
} }
short GenContext::GetParamsStackSize()
{
short acc = 0;
for (int i = 0; i < m_Proto.GetNumOfParams(); ++i)
{
acc += GetStackSize(m_Proto.GetParam(i));
}
// Memory return: address is first param
if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem)
acc += SIZE_PTR;
// :TODO: cdecl: THIS POINTER AS FIRST PARAM!!!
return acc;
}
void GenContext::GenerateCallOrig(int v_status, int v_pContext, int param_base_offs, int v_this, void GenContext::GenerateCallOrig(int v_status, int v_pContext, int param_base_offs, int v_this,
int v_vfnptr_origentry, int v_orig_ret, int v_override_ret, int v_place_for_memret) int v_vfnptr_origentry, int v_orig_ret, int v_override_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base)
{ {
jitoffs_t counter, tmppos; jitoffs_t counter, tmppos;
jitoffs_t counter2, tmppos2; jitoffs_t counter2, tmppos2;
@ -937,7 +997,7 @@ namespace SourceHook
m_HookFunc.start_count(counter2); m_HookFunc.start_count(counter2);
// push params // push params
jit_int32_t gcc_clean_bytes = PushParams(param_base_offs, v_orig_ret, v_place_for_memret); jit_int32_t gcc_clean_bytes = PushParams(param_base_offs, v_orig_ret, v_place_for_memret, v_place_fbrr_base);
// thisptr // thisptr
IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_this); IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_this);
@ -953,10 +1013,11 @@ namespace SourceHook
// cleanup // cleanup
#if SH_COMP == SH_COMP_GCC #if SH_COMP == SH_COMP_GCC
// params + thisptr
IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, gcc_clean_bytes + SIZE_PTR, MOD_REG); IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, gcc_clean_bytes + SIZE_PTR, MOD_REG);
#endif #endif
DestroyParams(v_place_fbrr_base);
// save retval // save retval
SaveRetVal(v_orig_ret, v_place_for_memret); SaveRetVal(v_orig_ret, v_place_for_memret);
@ -1167,6 +1228,9 @@ namespace SourceHook
// if required: // if required:
// my_rettype place_for_memret ebp - 28 - sizeof(my_rettype)*4 -4 // my_rettype place_for_memret ebp - 28 - sizeof(my_rettype)*4 -4
// gcc only: if required:
// place forced byref params ebp - 28 - sizeof(my_rettype)*{4 or 5}
const jit_int8_t v_vfnptr_origentry = -4 + addstackoffset; const jit_int8_t v_vfnptr_origentry = -4 + addstackoffset;
const jit_int8_t v_status = -8 + addstackoffset; const jit_int8_t v_status = -8 + addstackoffset;
@ -1196,11 +1260,14 @@ namespace SourceHook
jit_int32_t v_place_for_memret = -28 + addstackoffset - GetStackSize(m_Proto.GetRet()) * 4; jit_int32_t v_place_for_memret = -28 + addstackoffset - GetStackSize(m_Proto.GetRet()) * 4;
jit_int32_t v_place_fbrr_base = -28 + addstackoffset - GetStackSize(m_Proto.GetRet()) * (MemRetWithTempObj() ? 5 : 4);
// Hash for temporary storage for byval params with copy constructors // Hash for temporary storage for byval params with copy constructors
// (param, offset into stack) // (param, offset into stack)
short usedStackBytes = 3*SIZE_MWORD + 3*SIZE_PTR // vfnptr_origentry, status, prev_res, cur_res, iter, pContext short usedStackBytes = 3*SIZE_MWORD + 3*SIZE_PTR // vfnptr_origentry, status, prev_res, cur_res, iter, pContext
+ 3 * GetStackSize(m_Proto.GetRet()) + (m_Proto.GetRet().size == 0 ? 0 : SIZE_PTR) // ret_ptr, orig_ret, override_ret, plugin_ret + 3 * GetStackSize(m_Proto.GetRet()) + (m_Proto.GetRet().size == 0 ? 0 : SIZE_PTR) // ret_ptr, orig_ret, override_ret, plugin_ret
+ (MemRetWithTempObj() ? GetStackSize(m_Proto.GetRet()) : 0) + (MemRetWithTempObj() ? GetStackSize(m_Proto.GetRet()) : 0)
+ GetForcedByRefParamsSize()
- addstackoffset; // msvc: current thisptr - addstackoffset; // msvc: current thisptr
IA32_Sub_Rm_Imm32(&m_HookFunc, REG_ESP, usedStackBytes, MOD_REG); IA32_Sub_Rm_Imm32(&m_HookFunc, REG_ESP, usedStackBytes, MOD_REG);
@ -1244,15 +1311,15 @@ namespace SourceHook
// ********************** call pre hooks ********************** // ********************** call pre hooks **********************
GenerateCallHooks(v_status, v_prev_res, v_cur_res, v_iter, v_pContext, param_base_offs, GenerateCallHooks(v_status, v_prev_res, v_cur_res, v_iter, v_pContext, param_base_offs,
v_plugin_ret, v_place_for_memret); v_plugin_ret, v_place_for_memret, v_place_fbrr_base);
// ********************** call orig func ********************** // ********************** call orig func **********************
GenerateCallOrig(v_status, v_pContext, param_base_offs, v_this, v_vfnptr_origentry, v_orig_ret, GenerateCallOrig(v_status, v_pContext, param_base_offs, v_this, v_vfnptr_origentry, v_orig_ret,
v_override_ret, v_place_for_memret); v_override_ret, v_place_for_memret, v_place_fbrr_base);
// ********************** call post hooks ********************** // ********************** call post hooks **********************
GenerateCallHooks(v_status, v_prev_res, v_cur_res, v_iter, v_pContext, param_base_offs, GenerateCallHooks(v_status, v_prev_res, v_cur_res, v_iter, v_pContext, param_base_offs,
v_plugin_ret, v_place_for_memret); v_plugin_ret, v_place_for_memret, v_place_fbrr_base);
// ********************** end context and return ********************** // ********************** end context and return **********************
@ -1265,8 +1332,9 @@ namespace SourceHook
for (int i = 0; i < m_Proto.GetNumOfParams(); ++i) for (int i = 0; i < m_Proto.GetNumOfParams(); ++i)
{ {
const IntPassInfo &pi = m_Proto.GetParam(i); const IntPassInfo &pi = m_Proto.GetParam(i);
// GCC: NOT of forced byref params. the caller destructs those.
if (pi.type == PassInfo::PassType_Object && (pi.flags & PassInfo::PassFlag_ODtor) && if (pi.type == PassInfo::PassType_Object && (pi.flags & PassInfo::PassFlag_ODtor) &&
(pi.flags & PassInfo::PassFlag_ByVal)) (pi.flags & PassInfo::PassFlag_ByVal) && !(pi.flags & PassFlag_ForcedByRef))
{ {
IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, cur_param_pos); IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, cur_param_pos);
IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(pi.pDtor)); IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(pi.pDtor));
@ -1420,6 +1488,7 @@ namespace SourceHook
pi.type != PassInfo::PassType_Float && pi.type != PassInfo::PassType_Float &&
pi.type != PassInfo::PassType_Object) pi.type != PassInfo::PassType_Object)
{ {
printf("A\n");
return false; return false;
} }
@ -1427,17 +1496,29 @@ namespace SourceHook
(pi.flags & PassInfo::PassFlag_ByVal)) (pi.flags & PassInfo::PassFlag_ByVal))
{ {
if ((pi.flags & PassInfo::PassFlag_CCtor) && !pi.pCopyCtor) if ((pi.flags & PassInfo::PassFlag_CCtor) && !pi.pCopyCtor)
{
printf("B\n");
return false; return false;
}
if ((pi.flags & PassInfo::PassFlag_ODtor) && !pi.pDtor) if ((pi.flags & PassInfo::PassFlag_ODtor) && !pi.pDtor)
{
printf("C\n");
return false; return false;
}
if ((pi.flags & PassInfo::PassFlag_AssignOp) && !pi.pAssignOperator) if ((pi.flags & PassInfo::PassFlag_AssignOp) && !pi.pAssignOperator)
{
printf("D\n");
return false; return false;
}
if ((pi.flags & PassInfo::PassFlag_OCtor) && !pi.pNormalCtor) if ((pi.flags & PassInfo::PassFlag_OCtor) && !pi.pNormalCtor)
{
printf("D\n");
return false; return false;
} }
}
if ((pi.flags & (PassInfo::PassFlag_ByVal | PassInfo::PassFlag_ByRef)) == 0) if ((pi.flags & (PassInfo::PassFlag_ByVal | PassInfo::PassFlag_ByRef)) == 0)
{ {
@ -1505,8 +1586,7 @@ namespace SourceHook
if (pi.type == PassInfo::PassType_Object && if (pi.type == PassInfo::PassType_Object &&
(pi.flags & PassInfo::PassFlag_ODtor)) (pi.flags & PassInfo::PassFlag_ODtor))
{ {
pi.flags &= ~PassInfo::PassFlag_ByVal; pi.flags |= PassFlag_ForcedByRef;
pi.flags |= PassInfo::PassFlag_ByRef;
} }
} }
#endif #endif

View File

@ -156,6 +156,7 @@ namespace SourceHook
{ {
const static int SIZE_MWORD = 4; const static int SIZE_MWORD = 4;
const static int SIZE_PTR = sizeof(void*); const static int SIZE_PTR = sizeof(void*);
const static int PassFlag_ForcedByRef = (1<<30); // ByVal in source, but actually passed by reference (GCC) -> private pass, destruct
CProto m_Proto; CProto m_Proto;
int m_VtblOffs; int m_VtblOffs;
@ -180,19 +181,22 @@ namespace SourceHook
// size info // size info
jit_int32_t GetRealSize(const IntPassInfo &info); jit_int32_t GetRealSize(const IntPassInfo &info);
jit_int32_t GetStackSize(const IntPassInfo &info); jit_int32_t GetStackSize(const IntPassInfo &info);
short GetParamsStackSize(); // sum(GetStackSize(i), 0 <= i < numOfParams) short GetParamsStackSize(); // sum(GetStackSize(param[i]), 0 <= i < numOfParams)
// Helpers // Helpers
void BitwiseCopy_Setup(); void BitwiseCopy_Setup();
void BitwiseCopy_Do(size_t size); void BitwiseCopy_Do(size_t size);
// Param push // Param push
short GetForcedByRefParamsSize(); // sum(param[i] is forcedbyref ? GetStackSize(param[i]) : 0, 0 <= i < numOfParams)
short GetForcedByRefParamOffset(int p); // sum(param[i] is forcedbyref ? GetStackSize(param[i]) : 0, 0 <= i < p)
jit_int32_t PushParams(jit_int32_t param_base_offset, jit_int32_t save_ret_to, jit_int32_t PushParams(jit_int32_t param_base_offset, jit_int32_t save_ret_to,
jit_int32_t v_place_for_memret); // save_ret_to and v_place_for_memret only used for memory returns jit_int32_t v_place_for_memret, jit_int32_t v_place_fbrr_base); // save_ret_to and v_place_for_memret only used for memory returns
jit_int32_t PushRef(jit_int32_t param_offset, const IntPassInfo &pi); jit_int32_t PushRef(jit_int32_t param_offset, const IntPassInfo &pi);
jit_int32_t PushBasic(jit_int32_t param_offset, const IntPassInfo &pi); jit_int32_t PushBasic(jit_int32_t param_offset, const IntPassInfo &pi);
jit_int32_t PushFloat(jit_int32_t param_offset, const IntPassInfo &pi); jit_int32_t PushFloat(jit_int32_t param_offset, const IntPassInfo &pi);
jit_int32_t PushObject(jit_int32_t param_offset, const IntPassInfo &pi); jit_int32_t PushObject(jit_int32_t param_offset, const IntPassInfo &pi, jit_int32_t v_place_fbrr);
void DestroyParams(jit_int32_t fbrr_base);
// Ret val processing // Ret val processing
void SaveRetVal(jit_int32_t v_where, jit_int32_t v_place_for_memret); void SaveRetVal(jit_int32_t v_where, jit_int32_t v_place_for_memret);
@ -205,11 +209,11 @@ namespace SourceHook
// Call hooks // Call hooks
void GenerateCallHooks(int v_status, int v_prev_res, int v_cur_res, int v_iter, void GenerateCallHooks(int v_status, int v_prev_res, int v_cur_res, int v_iter,
int v_pContext, int base_param_offset, int v_plugin_ret, int v_place_for_memret); int v_pContext, int base_param_offset, int v_plugin_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base);
// Call orig // Call orig
void GenerateCallOrig(int v_status, int v_pContext, int param_base_offs, int v_this, void GenerateCallOrig(int v_status, int v_pContext, int param_base_offs, int v_this,
int v_vfnptr_origentry, int v_orig_ret, int v_override_ret, int v_place_for_memret); int v_vfnptr_origentry, int v_orig_ret, int v_override_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base);
// Hook loop // Hook loop
void CallSetupHookLoop(int v_orig_ret, int v_override_ret, void CallSetupHookLoop(int v_orig_ret, int v_override_ret,

View File

@ -114,7 +114,7 @@ namespace
template <int MYSIZE> template <int MYSIZE>
std::ostream& operator <<(std::ostream &os, const Object<MYSIZE> &obj) std::ostream& operator <<(std::ostream &os, const Object<MYSIZE> &obj)
{ {
os << "Some Obj!"; os << "Some Obj" << static_cast<int>(obj.x[0]);
return os; return os;
} }

View File

@ -40,10 +40,6 @@ public:
template <class T> template <class T>
void *FindFuncAddr(T mfp) void *FindFuncAddr(T mfp)
{ {
if (sizeof(mfp) != sizeof(void*))
return NULL;
else
{
union union
{ {
T a; T a;
@ -51,7 +47,6 @@ void *FindFuncAddr(T mfp)
} u; } u;
u.a = mfp; u.a = mfp;
return u.b; return u.b;
}
} }
// Reference carrier // Reference carrier

View File

@ -40,10 +40,6 @@ public:
template <class T> template <class T>
void *FindFuncAddr(T mfp) void *FindFuncAddr(T mfp)
{ {
if (sizeof(mfp) != sizeof(void*))
return NULL;
else
{
union union
{ {
T a; T a;
@ -51,7 +47,6 @@ void *FindFuncAddr(T mfp)
} u; } u;
u.a = mfp; u.a = mfp;
return u.b; return u.b;
}
} }
// Reference carrier // Reference carrier