Quote:
Originally Posted by SeLfkiLL
Code:
#ifdef WIN32
typedef void (*func)(float, bool, float, bool);
func thisfunc = (func)CBaseAnimating_Ignite_Sig.sig_addr; // Pointer to the function scanned from memory
/* The CBaseAnimating object must be pushed onto the stack manually
for the real method to use (and thus its arguments as well). */
__asm {
mov ecx, cba;
push flFlameLifetime;
push bNPCOnly;
push flSize;
push bCalledByLevelDesigner;
call thisfunc;
};
#else
|
There's a better* way to call a member function in Win32 than all that asm crap. BAILOPAN actually mentioned it a few weeks ago in #sourcemod, and I just tested to see if it works about an hour ago, ironically. Keep in mind this is only for member functions that do not have variable arguments. To handle those, do it like GCC and pass
this as the first parameter. Here is the method BAILOPAN suggested:
Code:
#ifdef WIN32
/* the first parameter is the this pointer, the second is just a dummy, just pass 0 */
typedef void (__fastcall *func)(CBaseAnimating*, void*, float, bool, float, bool);
func thisfunc = (func)CBaseAnimating_Ignite_Sig.sig_addr; // Pointer to the function scanned from memory
thisfunc(cba, 0, flFlameLifetime, (bool)bNPCOnly, flSize, (bool)bCalledByLevelDesigner);
#else
Basically, the
fastcall calling convention passes the first 2 parameters (as long as they fit in a register, 32 or 64bits long) in ECX and EDX. As you already know, MSVC handles
thiscall by passing
this in ECX. By simply passing the CBA pointer and a dummy value in ECX and EDX via fastcall, we are putting the
this pointer right where it needs to be, and the dummy in EDX is ignored. Luckily both
thiscall and
fastcall have the callee clean the stack (which is why variable argument functions need to be handled normally like
cdecl).
*I'm sure 'better' is a point of contention here. Personally, I just never liked using possibly nonportable inline asm to do things that could be done without it. Granted the 6 ops you used are hardly nonportable, but it's the principle.