Здравствуйте, Слава, Вы писали:
С>Здравствуйте.
С>А можно как нибудь заставить работать такое:
Напрямую — нет.
Причины:
— коллбеки 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;
});
}
Здравствуйте, 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";
});
}
Здравствуйте, 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 { ..... } )
);
.....
Здравствуйте, Кодт, Вы писали:
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 { ..... } )
К> );
К>.....
К>
а это уже что-то... идея красивая. спасибо — попробую.