#include <iostream>
#include <string>
#include <vector>
#include <cstdarg>
using namespace std;
//maly singleton do tworzenia id dla kolejnych callbackow
class CCallbackIdCreator
{
private:
unsigned int m_dLastId;
public:
CCallbackIdCreator()
{
m_dLastId = 0;
}
static CCallbackIdCreator& inst()
{
static CCallbackIdCreator m_inst;
return m_inst;
}
private:
unsigned int getId()
{
return ++m_dLastId;
}
friend class Callback;
};
//container (handler)
class Callback
{
private:
//nasze najpotrzebniejsze wskazniki
void* m_pThis;
void* m_pFunc;
int* m_vpParameters;
unsigned int m_dNumParameters;
//takie krotkie info :P
int m_bIsInstantiated;
//id
unsigned int m_id;
public:
//konstruktory ogolne
Callback()
{
m_vpParameters = NULL;
Reset();
}
Callback( const Callback& obj )
{
Reset( obj );
}
//destruktor dla niektorych kompilatorow bez wyobrazni
~Callback()
{
}
//konstruktory dla funkcji
Callback( int parNum, ... )
{
va_list list;
va_start( list, parNum );
m_pThis = va_arg( list, void* );
m_pFunc = va_arg( list, void* );
m_dNumParameters = parNum;
m_vpParameters = new int[parNum];
for( int i = parNum - 1; i >= 0; i -- )
m_vpParameters[i] = va_arg( list, int );
va_end( list );
m_bIsInstantiated = true;
m_id = CCallbackIdCreator::inst().getId();
}
//wywolanie metody/funkcji
void call( void* par = NULL )
{
callInt( par );
}
//usuwa stare parametry i ustawia nowe
int callInt( unsigned int parsNum, ... )
{
va_list list;
delete[] m_vpParameters;
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 );
}
//wywolanie metody/funkcji ze zwrotem parametru
int callInt( void* par = NULL )
{
if( par != NULL )
{
delete[] m_vpParameters;
m_vpParameters = new int[1];
m_vpParameters[0] = (int)par;
m_dNumParameters = 1;
}
if( m_bIsInstantiated )
{
void* pFunc = (void*) m_pFunc;
int dSize = 0;
int dNumParameters = m_dNumParameters;
int dOut = 0;
/* w tym miejscu wszystkie parametry sa juz ustawione w odpowiedniej konwencji wywolania */
int* pParameter = &m_vpParameters[0];
__asm
{
mov ecx, 0 //zerujemy iterator
//while( true )
our_for: //{
cmp ecx, [dNumParameters] //if( i < dNumParameters )
jae end_our_for //goto end_our_for;
mov ebx, pParameter //wrzucamy parametr ze wskaznika
push [ebx] //na stos
add ecx, 1 //i++;
add dSize, 4 //zwiekszamy wielkosc oczyszczajaca stos
add pParameter, 4 //wybieramy nastepny parametr
jmp our_for
end_our_for: //}
mov ecx, [m_pThis]; //ustawiamy funkcje i wywolujemy ja
call near pFunc; //
add esp, [dSize] //czas oczyscic stos
mov [dOut], eax; //umieszczamy wynik w zmiennej
//potrzebne to jest w zasadzie
//tylko dla wywolania callInt
//ale nic nie stoi na przeszkodzie
//aby wywolac to takze dla void
}
return dOut;
}
//aby kompilator sie nie plul w zasadzie :P
return 0;
}
void operator= ( const Callback& obj )
{
Reset( obj );
}
bool operator== ( const Callback& obj ) const
{
if( m_id == m_id )
return true;
else
return false;
}
bool operator!= ( const Callback& obj ) const
{
if( m_id != obj.m_id )
return true;
else
return false;
}
void 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 Reset()
{
m_pThis = NULL;
m_pFunc = NULL;
delete[] m_vpParameters;
m_vpParameters = NULL;
m_dNumParameters = 0;
m_bIsInstantiated = NULL;
m_id = NULL;
}
};
/* test functions */
void some_func();
void some_func3_1( void* );
void some_func3_2( void* );
int some_func3_3( void* );
void some_func3_4( char* txt );
char* some_func3_5( char* someTxt, int someInt );
//test A
void some_func()
{
cout << "\tcalled some_func" << endl;
}
//test B
int some_func3_3( void* myInt )
{
int dTmp = (int) myInt;
cout << "\tcalled some_func3_3" << endl << "\t\tgot param: " << dTmp << endl << "\t\tret val: ";
if( dTmp != 4 )
{
cout << "false (par != 4)" << endl;
return false;
}
cout << "true (par == 4)" << endl;
return true;
}
//test C
//global func inside another func
Callback c( 0, &some_func3_1, &some_func3_2 );
void some_func3_2( void* myInt )
{
int dTmp = (int) myInt;
cout << "\tcalled some_func3_2" << endl << "\t\tgot param: " << dTmp << endl;
}
void some_func3_1( void* )
{
int myPrivateInt = 6;
c.call( (void*) myPrivateInt );
}
//test D
class SomeClass
{
public:
SomeClass(){}
~SomeClass(){}
void someMethod( void* par )
{
cout << "\tcalled someMethod" << endl;
if( par != NULL )
cout << "\t\tgot param: " << ((int)par) << endl;
}
};
//test E
void some_func3_4( char* txt )
{
cout << "\tcalled some_func3_4" << endl;
cout << "\t\tpar(txt): " << txt << endl;
}
//test F
char* some_func3_5( char* someTxt, int someInt )
{
cout << "\tcalled some_func3_5" << endl;
cout << "\t\tsomeTxt: " << someTxt << endl;
cout << "\t\tsomeInt: " << someInt << endl;
char* tmpTxt = new char[5];
memset( tmpTxt, 0, 5 );
tmpTxt[0] = 32;
tmpTxt[1] = 65;
return tmpTxt;
}
//test A, B, C, D, E, F
int main( int argc, char* argv[] )
{
//class method
SomeClass obj;
Callback d( 1, &obj, &SomeClass::someMethod, 0 );
//global func
Callback a( 0, 0, &some_func );
Callback b( 1, 0, &some_func3_3, (void*)4 );
char pszStr[] = "jakies info do przekazania";
Callback e( 1, &main, &some_func3_4, pszStr );
int dInt = 613;
Callback f( 2, &main, &some_func3_5, pszStr, dInt );
//calling
cout << "void:" << endl;
a.call();
a.call( (void*) 123 );
d.call();
d.call( (void*) 5 );
some_func3_1( 0 );
cout << endl << "int: " << endl;
int ourBool = b.callInt();
e.call();
char* tmpTxt = (char*)f.callInt();
cout << "\t\treturn: " << tmpTxt << endl;
getchar();
return 0;
}