Last active
August 29, 2015 14:08
-
-
Save Namek/109efb78a575418c6346 to your computer and use it in GitHub Desktop.
C++ inline Assembler hack back in 2008.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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