Re: Лямбду в WinAPI
От: 0xDEADBEEF Ниоткуда  
Дата: 16.12.11 11:24
Оценка:
Здравствуйте, Слава, Вы писали:

С>Здравствуйте.


С>А можно как нибудь заставить работать такое:

Напрямую — нет.
Причины:
— коллбеки Win32Api имеют соглашение вызова stdcall, а сишные функции — cdecl
— твоя лямбда захватывает переменные. Такая лямбда не может быть приведена к типу "указатель на функцию".

А вот так — работает (GCC-4.6, MSVC-10), причем без всяких извращений с std::function
//CC G++
//G++-FLAGS -Xdebug -O0 -std=gnu++0x -- -lstdc++
#include <windows.h>
#include <iostream>
#include <string>

template<class LAMBDA>
BOOL CALLBACK EnumWindowsLambda(HWND hwnd, LPARAM lParam)
{
    return (*reinterpret_cast<LAMBDA*>(lParam))(hwnd);
}

template<class LAMBDA>
BOOL EnumWindows(LAMBDA lpEnumLambda)
{
    return EnumWindows(&EnumWindowsLambda<LAMBDA>, reinterpret_cast<LPARAM>(&lpEnumLambda));
}

int main()
{
    std::string title = "HWND:";
    EnumWindows([&](HWND hwnd) -> BOOL {
        std::cout << title << std::hex << hwnd << std::endl;
        return TRUE;
    });
}
__________
16.There is no cause so right that one cannot find a fool following it.
Re[2]: Лямбду в WinAPI
От: 0xDEADBEEF Ниоткуда  
Дата: 16.12.11 12:23
Оценка: 13 (1)
Здравствуйте, 0xDEADBEEF, Вы писали:

Версия №2 — принимает только лямбды с нужным набором параметров. Причем эти параметры описаны в определении функции.
И, заодно убрана лишняя функция из глобального скопа.
BOOL EnumWindows(std::function<BOOL(HWND)> const& cb)
{
    typedef std::function<BOOL(HWND)> cbtype;
    struct cbwrap {
        static BOOL CALLBACK cb(HWND hwnd, LPARAM lParam)
        {
            return (*reinterpret_cast<cbtype*>(lParam))(hwnd);
        }
    };
    return EnumWindows(&cbwrap::cb, reinterpret_cast<LPARAM>(&cb));
}

int main()
{
    std::string title = "HWND:";
        //это сработает, тк. параметры лямбды полностью совпадают
    EnumWindows([&](HWND hwnd) -> BOOL {
        std::cout << title << std::hex << hwnd << std::endl;
        return TRUE;
    });
        //это не сработает, тк. параметры лямбды не совпадают
    EnumWindows([&](HWND hwnd) -> std::string {
        return "aaaa";
    });
}
__________
16.There is no cause so right that one cannot find a fool following it.
Re[3]: Лямбду в WinAPI
От: Кодт Россия  
Дата: 16.12.11 14:15
Оценка:
Здравствуйте, 23W, Вы писали:

23W>Эта идей не работает, т.к. все калбеки имеют разный список параметров... что писать под каждый из них enumwindows_thunk ? толку тогда от лябды... ведь основная идея была уйти от статических функций в своем коде.


Если есть более чем одно замыкание-колбек для EnumWindow, то идея работает. Без этого пришлось бы заводить структуру для передачи данных из контекста.
Что-то такое
void foo()
{
  ...
  struct args
  {
    HWND& found; DWORD procid;
    static BOOL CALLBACK ewp(HWND w, LPARAM p) { return (*(args*)p)->ewp(w); }
    BOOL ewp() { ..... }
  } a;
  EnumWindows(args::ewp, &a);
  ...
}

Ну не мрак ли?

23W>Шаблоном к сожалению тут тоже не помочь. Можно сделать шаблоную ф-ю с форматом вызова __stdcall которая бы вызывала экивиалентную ей по списку параметров лямбду, но как эту лямбду передать в шаблон ?


А примерно так
template<class CB> struct callback;

template<class F> struct callback_base
{
  typedef function<F> closure_type;
  static LPARAM param(closure_type const& f) { return (LPARAM)&f; }
};

template<class R> struct callback<R (CALLBACK*)(LPARAM)> : callback_base<R(LPARAM)>
{
  static R CALLBACK thunk(LPARAM p) { return (*(closure_type*)p)(); }
};
template<class R, class A1> struct callback<R (CALLBACK*)(A1, LPARAM)> : callback_base<R(A1,LPARAM)>
{
  static R CALLBACK thunk(A1 a1, LPARAM p) { return (*(closure_type*)p)(a1); }
};
template<class R, class A1, class A2> struct callback<R (CALLBACK*)(A1, A2, LPARAM)> : callback_base<R(A1,A2,LPARAM)>
{
  static R CALLBACK thunk(A1 a1, A2 a2, LPARAM p) { return (*(closure_type*)p)(a1,a2); }
};
.....

.....
  EnumWindow(
    callback<ENUMWINDOWPROC>::thunk,
    callback<ENUMWINDOWPROC>::param( [](HWND)->BOOL { ..... } )
  );
.....
Перекуём баги на фичи!
Re[4]: Лямбду в WinAPI
От: 23W http://kyselgov.pp.ua/
Дата: 16.12.11 14:23
Оценка:
Здравствуйте, Кодт, Вы писали:

23W>>Шаблоном к сожалению тут тоже не помочь. Можно сделать шаблоную ф-ю с форматом вызова __stdcall которая бы вызывала экивиалентную ей по списку параметров лямбду, но как эту лямбду передать в шаблон ?


К>А примерно так

К>
К>template<class CB> struct callback;

К>template<class F> struct callback_base
К>{
К>  typedef function<F> closure_type;
К>  static LPARAM param(closure_type const& f) { return (LPARAM)&f; }
К>};

К>template<class R> struct callback<R (CALLBACK*)(LPARAM)> : callback_base<R(LPARAM)>
К>{
К>  static R CALLBACK thunk(LPARAM p) { return (*(closure_type*)p)(); }
К>};
К>template<class R, class A1> struct callback<R (CALLBACK*)(A1, LPARAM)> : callback_base<R(A1,LPARAM)>
К>{
К>  static R CALLBACK thunk(A1 a1, LPARAM p) { return (*(closure_type*)p)(a1); }
К>};
К>template<class R, class A1, class A2> struct callback<R (CALLBACK*)(A1, A2, LPARAM)> : callback_base<R(A1,A2,LPARAM)>
К>{
К>  static R CALLBACK thunk(A1 a1, A2 a2, LPARAM p) { return (*(closure_type*)p)(a1,a2); }
К>};
К>.....

К>.....
К>  EnumWindow(
К>    callback<ENUMWINDOWPROC>::thunk,
К>    callback<ENUMWINDOWPROC>::param( [](HWND)->BOOL { ..... } )
К>  );
К>.....
К>


а это уже что-то... идея красивая. спасибо — попробую.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.