Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > инициализация указателя на функцию


Автор: GoldFinch 29.3.2010, 18:30
Код

typedef int (*FARPROC)();
FARPROC GetProcAddress()
{
    return 0;
}

int main()
{
    void (*bar)(int);
    (FARPROC&)bar = GetProcAddress();
}

хочется записать объявление и инициализацию bar в 1 строчку

вот такой вариант, хоть и в 1 строчку, но длинный и не красивый
void (*bar)(int) = (void(*)(int))GetProcAddress();

Автор: mes 29.3.2010, 18:41
Цитата(GoldFinch @  29.3.2010,  17:30 Найти цитируемый пост)
void (*bar)(int) = (void(*)(int))GetProcAddress(); 

позвольте узнать, чем не подходит такое :
Код

    FARPROC bar = GetProcAddress();


Цитата(GoldFinch @  29.3.2010,  17:30 Найти цитируемый пост)
объявление и инициализацию

придераюсь: объявление (хотя лучше определение) и присвоение smile

Автор: GoldFinch 29.3.2010, 18:47
mes, не подходит, т.к. потом при вызове bar мне придется кастовать ее к ее сигнатуре

((void(*)(int))*bar)(100);

Автор: Earnest 29.3.2010, 18:57
Я всегда объявляю типы для функций:
typedef void (*FDoSomething)(int);

Тогда и объявление и получение выглядят вполне прилично:
FDoSomething bar = (FDoSomething) GetProcAddress();


Автор: GoldFinch 29.3.2010, 19:01
Earnest, не хотеть в 2 строчки! хотеть в 1 строчку!

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

Автор: mes 29.3.2010, 19:03
Цитата(GoldFinch @  29.3.2010,  18:01 Найти цитируемый пост)
я хочу сделать импортируемые функции глобальными переменными, импортировать их 1 раз,
и по этому мне не нужны отдельно их типы 

ну а если сделать шаблонный враппер, имеющий нужные преобразования ?

Автор: GoldFinch 29.3.2010, 19:04
счя набросал вот такой кодес, вроде выглядит красиво
Код

//-------------------- test function ------------------------
void test_in_another_module(int)
{
   cout << "test called\n";
}

//----------------- windows.h ---------------------------
typedef int (*FARPROC)();
FARPROC GetProcAddress(const char* /*name*/)
{
    return (FARPROC)&test_in_another_module;
}

//---------------------- my_api_import.h ------------
#include <boost/function.hpp>

template<typename Signature>
struct api_function : boost::function<Signature>
{
   typedef boost::function<Signature> base_t;
   api_function(FARPROC rhs) : base_t((Signature*)rhs) {}
};

//-------------------usage...--------------------------------
int main()
{
   api_function<void(int)>test = GetProcAddress("test");
   test(100);
}


Добавлено через 21 секунду
mes, да)

Добавлено через 2 минуты и 16 секунд
а еще лучше вот так
Код

//---------------------- my_api_import.h ------------
#include <boost/function.hpp>
template<typename Signature>
struct api_function : boost::function<Signature>
{
   typedef boost::function<Signature> base_t;
   api_function(const char* name) 
      : base_t((Signature*)GetProcAddress(name)) 
   {}
};
//-------------------usage...--------------------------------
int main()
{
   api_function<void(int)>test("test");
   test(100);
}

Автор: Earnest 29.3.2010, 19:10
Ну ты капризный...
По-другому (чем ты уже писал) в одну строчку не получится.

Ну можно еще макросами. Т.е. раскрывать будет как у тебя, а в коде будет примерно так:

DECLARE_FUNCTION (void (*)(int), bar, "NameForGetProcAddress")

Так тебе красиво?

Автор: GoldFinch 29.3.2010, 19:20
Earnest, не, макросами не красиво
хотя для случаев когда нет (boost|tr1)::function - подойдет

Автор: GoldFinch 29.3.2010, 19:40
осталось только победить __stdcall  =\

Автор: GoldFinch 29.3.2010, 21:44
угу, (boost|tr1)::function не поддерживает stdcall, использовать bind который поддерживает stdcall - это малость оверхед, да и сам function - немалый оверхед (~32байта на указатель)

а свои классы выглядят страшно %)
Код

#ifndef API_FUNCTION_H_INCLUDED_
#define API_FUNCTION_H_INCLUDED_

/* Windows API Dynamic Import
 *
 * Example:

api_function<void()> foo("some.dll", "foo");
....
foo();

 *
 */

#include <windows.h>

namespace detail {

template<typename Signature> struct stdcall_function_ptr;

struct stdcall_function_address
{
    typedef void* ptr_t;
    ptr_t ptr;
};

/* ================= stdcall_function_ptr code was generated by following Python script: =============

def num_list(pfx, n): return ', '.join(pfx + str(i) for i in range(n))
def num_pairs(pfx1, pfx2, n): return ', '.join(pfx1 + str(i) + ' ' + pfx2 + str(i) for i in range(n))
for i in range(16): print("""
template<typename R, """ + num_list('typename T', i) + """>
struct stdcall_function_ptr<R(""" + num_list('T', i) + """)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(""" + num_list('T', i) + """);
    R operator() (""" + num_pairs('T', 'a', i) + """) { return (*(fn_t)ptr)(""" + num_list('a', i) + """); }
};""")

*/

template<typename R, >
struct stdcall_function_ptr<R()> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)();
    R operator() () { return (*(fn_t)ptr)(); }
};

template<typename R, typename T0>
struct stdcall_function_ptr<R(T0)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0);
    R operator() (T0 a0) { return (*(fn_t)ptr)(a0); }
};

template<typename R, typename T0, typename T1>
struct stdcall_function_ptr<R(T0, T1)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1);
    R operator() (T0 a0, T1 a1) { return (*(fn_t)ptr)(a0, a1); }
};

template<typename R, typename T0, typename T1, typename T2>
struct stdcall_function_ptr<R(T0, T1, T2)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1, T2);
    R operator() (T0 a0, T1 a1, T2 a2) { return (*(fn_t)ptr)(a0, a1, a2); }
};

template<typename R, typename T0, typename T1, typename T2, typename T3>
struct stdcall_function_ptr<R(T0, T1, T2, T3)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1, T2, T3);
    R operator() (T0 a0, T1 a1, T2 a2, T3 a3) { return (*(fn_t)ptr)(a0, a1, a2, a3); }
};

template<typename R, typename T0, typename T1, typename T2, typename T3, typename T4>
struct stdcall_function_ptr<R(T0, T1, T2, T3, T4)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1, T2, T3, T4);
    R operator() (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4) { return (*(fn_t)ptr)(a0, a1, a2, a3, a4); }
};

template<typename R, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
struct stdcall_function_ptr<R(T0, T1, T2, T3, T4, T5)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1, T2, T3, T4, T5);
    R operator() (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { return (*(fn_t)ptr)(a0, a1, a2, a3, a4, a5); }
};

template<typename R, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
struct stdcall_function_ptr<R(T0, T1, T2, T3, T4, T5, T6)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1, T2, T3, T4, T5, T6);
    R operator() (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) { return (*(fn_t)ptr)(a0, a1, a2, a3, a4, a5, a6); }
};

template<typename R, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
struct stdcall_function_ptr<R(T0, T1, T2, T3, T4, T5, T6, T7)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1, T2, T3, T4, T5, T6, T7);
    R operator() (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7) { return (*(fn_t)ptr)(a0, a1, a2, a3, a4, a5, a6, a7); }
};

template<typename R, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
struct stdcall_function_ptr<R(T0, T1, T2, T3, T4, T5, T6, T7, T8)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1, T2, T3, T4, T5, T6, T7, T8);
    R operator() (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8) { return (*(fn_t)ptr)(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
};

template<typename R, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
struct stdcall_function_ptr<R(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
    R operator() (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9) { return (*(fn_t)ptr)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
};

template<typename R, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
struct stdcall_function_ptr<R(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
    R operator() (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10) { return (*(fn_t)ptr)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
};

template<typename R, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11>
struct stdcall_function_ptr<R(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
    R operator() (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11) { return (*(fn_t)ptr)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
};

template<typename R, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12>
struct stdcall_function_ptr<R(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
    R operator() (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12) { return (*(fn_t)ptr)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
};

template<typename R, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13>
struct stdcall_function_ptr<R(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
    R operator() (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13) { return (*(fn_t)ptr)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
};

template<typename R, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14>
struct stdcall_function_ptr<R(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)> : stdcall_function_address
{
    typedef R(__stdcall *fn_t)(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
    R operator() (T0 a0, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10, T11 a11, T12 a12, T13 a13, T14 a14) { return (*(fn_t)ptr)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
};

} // namespace detail

template<typename Signature>
struct api_function : detail::stdcall_function_ptr<Signature>
{
    api_function(HMODULE hModule, const char* functionName) 
    {
        ptr = (ptr_t)GetProcAddress(hModule, functionName);
    }
    api_function(const char* moduleName, const char* functionName)
    {
        ptr = (ptr_t)GetProcAddress(LoadLibraryA(moduleName), functionName);
    }
};

#endif // API_FUNCTION_H_INCLUDED_

Автор: mes 29.3.2010, 22:58
Цитата(GoldFinch @  29.3.2010,  20:44 Найти цитируемый пост)
а свои классы выглядят страшно %)

Цитата(GoldFinch @  29.3.2010,  20:44 Найти цитируемый пост)
  R operator() (T0 a0, T1 a1, T2 a2) { return (*(fn_t)ptr)(a0, a1, a2); }

угу, а что разве такое не работает ? :
Код

typedef void (*FN)();

template <class T>
struct fn_wrapper {
    fn_wrapper (FN fn): m_fn( (T)fn) {}
    
    operator T () { return m_fn; }
    
    T m_fn;
};


   fn_wrapper<void (__stdcall *)(int)> f1 = ... ;

сорри за грязный код..сейчас времени больше  нет smile

Автор: GoldFinch 29.3.2010, 23:10
хм... про operator T я не подумал

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)