Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@Namek
Last active August 29, 2015 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Namek/109efb78a575418c6346 to your computer and use it in GitHub Desktop.
Save Namek/109efb78a575418c6346 to your computer and use it in GitHub Desktop.
C++ inline Assembler hack back in 2008.
#include "stdafx.hpp"
using namespace NFR;
//
// CCallbackIdCreator
//
CCallbackIdCreator::CCallbackIdCreator()
{
m_dLastId = 0;
}
CCallbackIdCreator& CCallbackIdCreator::inst()
{
static CCallbackIdCreator m_inst;
return m_inst;
}
unsigned int CCallbackIdCreator::getId()
{
return ++m_dLastId;
}
//
// Callback
//
Callback::Callback()
{
m_vpParameters = NULL;
Reset();
}
Callback::Callback( const Callback& obj )
{
Reset( obj );
}
Callback::~Callback()
{
}
Callback::Callback( int parsNum, ... )
{
va_list list;
va_start( list, parsNum );
m_pThis = va_arg( list, void* );
m_pFunc = va_arg( list, void* );
m_dNumParameters = parsNum;
m_vpParameters = NULL;
if( parsNum )
{
m_vpParameters = new int[parsNum];
for( int i = parsNum - 1; i >= 0; i -- )
m_vpParameters[i] = va_arg( list, int );
}
va_end( list );
m_bIsInstantiated = true;
m_id = CCallbackIdCreator::inst().getId();
}
void Callback::call( void* par )
{
callInt( par );
}
int Callback::callInt( unsigned int parsNum, ... )
{
va_list list;
delete[] m_vpParameters;
m_vpParameters = NULL;
if( parsNum )
{
m_vpParameters = new int[parsNum];
va_start( list, parsNum );
for( unsigned int i = parsNum - 1; i >= 0; i -- )
va_arg( list, int );
va_end( list );
}
return callInt();
}
int Callback::callInt( void* par )
{
if( par != NULL )
{
setPar( par );
}
if( m_bIsInstantiated )
{
void* pFunc = (void*) m_pFunc;
void* pThis = m_pThis;
int dSize = 0;
int dNumParameters = m_dNumParameters;
int dOut = 0;
// here paramters are set in proper convention's call order
int* pParameter = m_vpParameters;
__asm
{
mov ecx, 0 // nullify iterator
// while( true )
our_for: // {
cmp ecx, [dNumParameters] // if( i < dNumParameters )
jae end_our_for // goto end_our_for;
mov ebx, pParameter // put parameter on the stack
push [ebx]
add ecx, 1 // i++;
add dSize, 4 // increase the stack size
add pParameter, 4 // choose next parameter pointer
jmp our_for
end_our_for: // }
mov ecx, pThis; // call the function
call pFunc; //
add esp, [dSize] // clear the stack
mov [dOut], eax; // put the `int` result into `dOut` variable.
// It's only needed for `callInt` but
// it's no error to use it in void function.
}
return dOut;
}
// for compiler's happiness
return 0;
}
void Callback::setPar( void* par )
{
setPars( 0 );
}
void Callback::setPars( int parsNum, ... )
{
va_list list;
delete[] m_vpParameters;
m_vpParameters = NULL;
if( parsNum )
{
m_vpParameters = new int[parsNum];
va_start( list, parsNum );
for( unsigned int i = parsNum - 1; i >= 0; i -- )
va_arg( list, int );
va_end( list );
}
}
unsigned int Callback::getId()
{
return m_id;
}
void Callback::operator= ( const Callback& obj )
{
Reset( obj );
}
bool Callback::operator== ( const Callback& obj ) const
{
if( m_id == m_id )
return true;
else
return false;
}
bool Callback::operator!= ( const Callback& obj ) const
{
if( m_id != obj.m_id )
return true;
else
return false;
}
void Callback::Reset( const Callback& obj )
{
m_pThis = obj.m_pThis;
m_pFunc = obj.m_pFunc;
m_dNumParameters = obj.m_dNumParameters;
m_vpParameters = new int[m_dNumParameters];
for( unsigned int i = 0; i < m_dNumParameters; i ++ )
m_vpParameters[i] = obj.m_vpParameters[i];
m_bIsInstantiated = obj.m_bIsInstantiated;
m_id = obj.m_id;
}
void Callback::Reset()
{
m_pThis = NULL;
m_pFunc = NULL;
delete[] m_vpParameters;
m_vpParameters = NULL;
m_dNumParameters = 0;
m_bIsInstantiated = NULL;
m_id = NULL;
}
Callback::operator bool() const
{
if( m_id )
return true;
return false;
}
#include <cstdarg>
namespace NFR
{
// ID factory made as singleton (oh dear)
class CCallbackIdCreator
{
private:
unsigned int m_dLastId;
public:
CCallbackIdCreator();
static CCallbackIdCreator& inst();
private:
unsigned int getId();
friend class Callback;
};
class Callback
{
private:
void* m_pThis;
void* m_pFunc;
int* m_vpParameters;
unsigned int m_dNumParameters;
// flag to be sure
int m_bIsInstantiated;
// id
unsigned int m_id;
public:
Callback();
Callback( const Callback& obj );
~Callback();
/* arguments:
* - parsNum
* - This
* - pFunc
* -x parameters
*/
Callback( int parsNum, ... );
// call method/function
void call( void* par = NULL );
// call; removes old parameters and sets new
int callInt( unsigned int parsNum, ... );
// call; parameter is being returned
int callInt( void* par = NULL );
// sets only one parameter
void setPar( void* par = NULL );
// set list of parameters
void setPars( int num, ... );
// gets id
unsigned int getId();
void operator= ( const Callback& obj );
bool operator== ( const Callback& obj ) const;
bool operator!= ( const Callback& obj ) const;
operator bool() const;
void Reset( const Callback& obj );
void Reset();
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment