обертка вызовов функций
От: K13 http://akvis.com
Дата: 25.03.09 10:54
Оценка:
Суть проблемы: в некоторых условиях, определяемых в рантайме (грубо -- выставлен флаг), мне при вызове любой функции из обширного АПИ требуются пляски с бубном:

1. построить в памяти переходник из ассемблерного кода и записать туда адрес реальной функции
2. вызвать адрес этого переходника, скастовав к типу реальной функции
3. по завершении освободить переходник.

очень не хочется руками писать обертки для каждой функции. их много. с разным числом и типом параметров.

есть смутное ощущение, что можно выкрутиться с помощью boost.FunctionTypes но никогда с этим не сталкивался.
Кто подскажет, куда рыть?
Re: обертка вызовов функций
От: K13 http://akvis.com
Дата: 25.03.09 11:12
Оценка:
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 );
Re[2]: обертка вызовов функций
От: SenkraD Украина  
Дата: 25.03.09 11:43
Оценка: 4 (1)
Здравствуйте, 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 );


Это?
Re[3]: обертка вызовов функций
От: K13 http://akvis.com
Дата: 25.03.09 12:25
Оценка:
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 или что-то другое...
Re[4]: обертка вызовов функций
От: K13 http://akvis.com
Дата: 25.03.09 12:45
Оценка:
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;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.