Суть проблемы: в некоторых условиях, определяемых в рантайме (грубо -- выставлен флаг), мне при вызове любой функции из обширного АПИ требуются пляски с бубном:
1. построить в памяти переходник из ассемблерного кода и записать туда адрес реальной функции
2. вызвать адрес этого переходника, скастовав к типу реальной функции
3. по завершении освободить переходник.
очень не хочется руками писать обертки для каждой функции. их много. с разным числом и типом параметров.
есть смутное ощущение, что можно выкрутиться с помощью boost.FunctionTypes но никогда с этим не сталкивался.
Кто подскажет, куда рыть?
K13>очень не хочется руками писать обертки для каждой функции. их много. с разным числом и типом параметров.
уточню:
хотелось бы вместо
int err = hugeAPI->funcptr( arg1, arg2, arg3 );
писать что-то вроде
int err = wrapper< hugeAPI::funcptr_t >( functpr )( arg1, arg2, arg3 );
при этом wrapper в конcтрукторе строит переходник, в operator() дергает его и в деструкторе освобождает переходник
если получится вот так, будет вообще замечательно:
int err = wrapper< hugeAPI->funcptr >( arg1, arg2, arg3 );
Здравствуйте, K13, Вы писали:
K13>>очень не хочется руками писать обертки для каждой функции. их много. с разным числом и типом параметров.
K13>уточню:
K13>хотелось бы вместо
K13>int err = hugeAPI->funcptr( arg1, arg2, arg3 );
K13>писать что-то вроде
K13>int err = wrapper< hugeAPI::funcptr_t >( functpr )( arg1, arg2, arg3 );
K13>при этом wrapper в конcтрукторе строит переходник, в operator() дергает его и в деструкторе освобождает переходник
K13>если получится вот так, будет вообще замечательно:
K13>int err = wrapper< hugeAPI->funcptr >( arg1, arg2, arg3 );
Это?
K13>>если получится вот так, будет вообще замечательно:
K13>>int err = wrapper< hugeAPI->funcptr >( arg1, arg2, arg3 );
SD>Это?
Hе совсем.
АПИ чужое, менять его нельзя. Это сишные структуры с кучей указателей на функции.
в этой статье используется особенность operator->() для проваливания куда надо и подстановки объекта. У меня вместо объекта указатель на функцию.
попробовал вот так:
typedef int (*func1_t)(int,void*);
typedef int (*func2_t)(int);
typedef int (*func3_t)(void*,void*,int);
struct API
{
func1_t func1;
func2_t func2;
func3_t func3;
};
template< typename T >
struct call_proxy_t
{
explicit call_proxy_t( T p ) : p_(p) {}
T operator->() { return p_; }
~call_proxy_t() { printf( "epilogue\n" ); }
private:
T p_;
};
template< typename T >
struct wrapped_t
{
explicit wrapped_t( T t ) : p_(t) {}
call_proxy_t<T> operator->()
{
printf( "prologue\n" );
return call_proxy_t<T>(p_);
}
private:
T p_;
};
template< typename T >
wrapped_t<T> wrapped( T& f )
{
return wrapped_t<T>( f );
}
void foo( API *api )
{
wrapped( api->func2 )->( 5 ); // error C2839: invalid return type 'int (__cdecl *)(int)' for overloaded 'operator ->'
}
пытался сделать объект-обертку, но та же фигня -- из operator->() нельзя возвращать указатель на функцию

а реализовать operator()() для произвольных аргументов у меня не получается.
Не знаю, может ли тут помочь boost.FunctionTypes или что-то другое...
K13>пытался сделать объект-обертку,
все, получилось:
#include <cstdio>
typedef int (*func1_t)(int,void*);
typedef int (*func2_t)(int);
typedef int (*func3_t)(void*,void*,int);
int real_func1(int,void*)
{
printf( "real_func1()\n" );
return 1;
}
int real_func2(int)
{
printf( "real_func2()\n" );
return 2;
}
int real_func3(void*,void*,int)
{
printf( "real_func3()\n" );
return 3;
}
struct API
{
func1_t func1;
func2_t func2;
func3_t func3;
};
API api = { real_func1, real_func2, real_func3 };
template< typename T >
struct wrap_t
{
wrap_t( T f ) { printf( "prologue\n" ); f_ = new T; *f_ = f; }
~wrap_t() { printf( "epilogue\n" ); delete f_; }
operator T()
{
printf( "operator T(), f_ = %p, *f_ = %p\n", f_, *f_ );
return *f_;
}
private:
T *f_;
};
template< typename T >
wrap_t<T> wrapped( T f )
{
return wrap_t<T>( f );
}
int main( int, char** )
{
printf( "api.func2 = %p\n", api.func2 );
wrapped( api.func2 )(5);
return 0;
}