int test(int a, int b) { return a + b; }
_test PROC ; ¥×¥í¥í¡¼¥° push ebp mov ebp, esp ; ËÜÂÎ mov eax, DWORD PTR 12[ebp] add eax, DWORD PTR 8[ebp] ; ¥¨¥Ô¥í¡¼¥° pop ebp ret 0 _test ENDP
_test PROC mov eax, DWORD PTR 12[esp-4] add eax, DWORD PTR 8[esp-4] ret 0 _test ENDP
push dword 1 push dword 2 push dword 3 pop eax pop ebx pop ecx
sub esp, 4 mov dword [esp], 1 sub esp, 4 mov dword [esp], 2 sub esp, 4 mov dword [esp], 3 mov eax, [esp] add esp, 4 mov ebx, [esp] add esp, 4 mov ecx, [esp] add esp, 4
; test(2, 3); push 3 push 2 call test add esp, 8
sub esp, 8 mov [esp+4], 3 mov [esp], 2 call test add esp, 8
http://kozos.jp/books/asm/
push 3 push 2 call test
test: mov eax, [esp+4] add eax, [esp+8] ret
#include <stdio.h> int test1(int a, int b) { return a + b; } _declspec(naked) int test2(int a, int b) { _asm { mov eax, 4[esp] add eax, 8[esp] ret } } int main() { printf("test1(2, 3): %d\n", test1(2, 3)); printf("test2(2, 3): %d\n", test2(2, 3)); }
#include <stdio.h> int test1(int a, int b) { return a + b; } extern "C" int test2(int, int); asm( "_test2:\n" " mov eax, dword ptr [esp+4]\n" " add eax, dword ptr [esp+8]\n" " ret\n"); int main() { printf("test1(2, 3): %d\n", test1(2, 3)); printf("test2(2, 3): %d\n", test2(2, 3)); }
int test2(int, int); asm( "__Z5test2ii:\n" " mov eax, dword ptr [esp+4]\n" " add eax, dword ptr [esp+8]\n" " ret\n");
*** ¤ª¤Þ¤±
#include <stdio.h> unsigned char testf[] = { 0x8b, 0x44, 0x24, 0x04, // mov eax, [esp+4] 0x03, 0x44, 0x24, 0x08, // add eax, [esp+8] 0xc3 // ret }; int main() { auto test = reinterpret_cast<int(*)(int, int)>(&testf); printf("test(2, 3): %d\n", test(2, 3)); }
*** NXÂкö
#include <windows.h> #include <stdio.h> #include <string.h> unsigned char testf[] = { 0x8b, 0x44, 0x24, 0x04, // mov eax, [esp+4] 0x03, 0x44, 0x24, 0x08, // add eax, [esp+8] 0xc3 // ret }; int main() { auto page = VirtualAlloc(nullptr, sizeof(testf), MEM_COMMIT, PAGE_EXECUTE_READWRITE); memcpy(page, testf, sizeof(testf)); auto test = reinterpret_cast<int(*)(int, int)>(page); printf("test(2, 3): %d\n", test(2, 3)); VirtualFree(page, 0, MEM_RELEASE); }
*** ´Ø¿ô¥Ý¥¤¥ó¥¿·¿¤Î¥³¥Ä¤ß¤¿¤¤¤Ê¤â¤Î¡£
#include <stdio.h> #include "xbyak/xbyak.h" struct TestFunc : public Xbyak::CodeGenerator { TestFunc() { mov(eax, ptr[esp+4]); add(eax, ptr[esp+8]); ret(); } }; int main() { TestFunc testf; auto test = reinterpret_cast<int(*)(int, int)>( const_cast<Xbyak::uint8 *>(testf.getCode())); printf("test(2, 3): %d\n", test(2, 3)); }
mov eax, [esp+4] add eax, [esp+8] ret
mov eax, [esp+4] add eax, [esp+8] ret 8
*** ´Ø¿ô¥Ý¥¤¥ó¥¿
mov eax, ecx add eax, edx ret
mov eax, [esp+4] ret 4
mov eax, [esp+8] ret
¶ñÂÎŪ¤Ë¤Ï¡¢°Ê²¼¤ÎConv¤òXbyak¤Ç¼ÂÁõ¤·¤Æ¤¯¤À¤µ¤¤¡£
#include <stdio.h> #include "xbyak/xbyak.h" void call(int(*p)(int, int), int a, int b) { printf("%d\n", p(a, b)); } int _stdcall test(int a, int b) { return a + b; } int main() { Conv c(test); auto f = reinterpret_cast<int(*)(int, int)>( const_cast<Xbyak::uint8 *>(c.getCode())); call(f, 2, 3); }
struct Conv : public Xbyak::CodeGenerator { Conv(int(_stdcall *p)(int, int)) { push(ptr[esp+8]); push(ptr[esp+8]); call(p); ret(); } };
#include <stdio.h> void test(int a) { printf("%d\n", a); } int main() { auto f = test; f(1); }
#include <stdio.h> struct Test { static void show(int n) { printf("%d\n", n); } }; int main() { auto f = Test::show; f(1); }
#include <stdio.h> void test(int a) { printf("%d\n", a); } struct Test { static void show(int n) { printf("%d\n", n); } }; void call(void (*f)(int), int a) { f(a); } int main() { call(test, 1); call(Test::show, 1); }
#include <stdio.h> struct Test { int n; Test(int n) : n(n) {} void show() { printf("%d\n", n); } }; int main() { Test t(1); auto f = &Test::show; (t.*f)(); }
void (Test::*f)() = &Test::show;
void test(); struct Test { void test(); } t; ¡û auto f1 = test; ¡û auto f2 = &test; ¡ß auto f3 = Test::test; ¡û auto f4 = &Test::test;
¡û f2(); ¡û (*f2)(); ¡ß (t.f4)(); ¡û (t.*f4)();
#include <stdio.h> struct Test1 { int n; Test1(int n) : n(n) {} void show() { printf("%d\n", n); } }; struct Test2 { int n; Test2(int n) : n(n) {} void show() { printf("%d\n", n); } }; struct Test3 { static void show() { printf("?\n"); } }; void show() { printf("!\n"); } void call(void (*f)()) { f(); } int main() { Test1 t1(1); Test2 t2(2); auto f1 = &Test1::show; auto f2 = &Test2::show; auto f3 = &Test3::show; auto f4 = &show; (t1.*f1)(); (t2.*f2)(); (*f3)(); (*f4)(); call(f3); call(f4); }
#include <stdio.h> struct Test { int n; Test(int n) : n(n) {} void operator()() { printf("%d\n", n); } }; int main() { Test t(1); t(); }
#include <stdio.h> int main() { int n = 1; auto t = [n] { printf("%d\n", n); }; t(); }
#include <functional> #include <stdio.h> struct Test1 { int n; Test1(int n) : n(n) {} void show() { printf("%d\n", n); } }; struct Test2 { int n; Test2(int n) : n(n) {} void show() { printf("%d\n", n); } }; struct Test3 { static void show() { printf("?\n"); } }; void show() { printf("!\n"); } void call(const std::function<void()> &f) { f(); } int main() { Test1 t1(1); Test2 t2(2); auto f1 = std::bind(&Test1::show, &t1); auto f2 = [&] { t2.show(); }; auto f3 = Test3::show; auto f4 = show; call(f1); call(f2); call(f3); call(f4); }
*** ¤ª¤Þ¤±
type Test1(n) = member x.show() = printfn "%d" n type Test2(n) = member x.show() = printfn "%d" n type Test3 = static member show() = printfn "?" let show() = printfn "!" let call f = f() let t1 = new Test1(1) let t2 = new Test2(2) let d1 = t1.show let d2 = fun() -> t2.show() let d3 = Test3.show let d4 = show call d1 call d2 call d3 call d4
#include <stdio.h> #include "xbyak/xbyak.h" template <class T> struct Delegate : public Xbyak::CodeGenerator { Delegate(T *t, void (T::*p)()) { mov(ecx, reinterpret_cast<intptr_t>(t)); jmp(*reinterpret_cast<void **>(&p)); } void (*getPtr())() { return reinterpret_cast<void (*)()>( const_cast<Xbyak::uint8 *>(getCode())); } }; struct Test1 { int n; Test1(int n) : n(n) {} void show() { printf("%d\n", n); } }; struct Test2 { int n; Test2(int n) : n(n) {} void show() { printf("%d\n", n); } }; struct Test3 { static void show() { printf("?\n"); } }; void show() { printf("!\n"); } void call(void (*f)()) { f(); } int main() { Test1 t1(1); Test2 t2(2); Delegate<Test1> d1(&t1, &Test1::show); Delegate<Test2> d2(&t2, &Test2::show); call(d1.getPtr()); call(d2.getPtr()); call(Test3::show); call(show); }
*** ´Ø¿ô¥Ý¥¤¥ó¥¿¤òÊÖ¤¹´Ø¿ô
#include <stdio.h> #include "xbyak/xbyak.h" template <class T, class TA1> struct Thunk : public Xbyak::CodeGenerator { Thunk(T *t, void (T::*p)(TA1)) { mov(ecx, reinterpret_cast<intptr_t>(t)); push(ptr[esp+4]); call(*reinterpret_cast<void **>(&p)); ret(); } void (*getPtr())(TA1) { return reinterpret_cast<void (*)(TA1)>( const_cast<Xbyak::uint8 *>(getCode())); } }; struct Test { int n; Test(int n) : n(n) {} void show(int n2) { printf("%d, %d\n", n, n2); } }; void show(int n) { printf("%d\n", n); } void call(void (*f)(int), int n) { f(n); } int main() { Test t(1); Thunk<Test, int> thunk(&t, &Test::show); call(thunk.getPtr(), 2); call(show, 3); }
#include <stdio.h> #include "xbyak/xbyak.h" struct Bind : public Xbyak::CodeGenerator { Bind(int(*f)(int, int), int a) { push(a); push(ptr[esp+8]); call(reinterpret_cast<void *>(f)); add(esp, 8); ret(); } int(*getPtr())(int) { return reinterpret_cast<int(*)(int)>( const_cast<Xbyak::uint8 *>(getCode())); } }; int add(int a, int b) { return a + b; } void call(int(*p)(int), int a) { printf("%d\n", p(a)); } int main() { Bind inc(add, 1); call(inc.getPtr(), 2); }
#include <functional> #include <stdio.h> #include "xbyak/xbyak.h" template <class T, class TA1, class TR> struct Thunk : public Xbyak::CodeGenerator { Thunk(T *f) { mov(ecx, reinterpret_cast<intptr_t>(f)); push(ptr[esp+4]); auto p = &T::operator(); call(*reinterpret_cast<void **>(&p)); ret(); } TR(*getPtr())(TA1) { return reinterpret_cast<TR(*)(TA1)>( const_cast<Xbyak::uint8 *>(getCode())); } }; int add(int a, int b) { return a + b; } void call(int(*p)(int), int a) { printf("%d\n", p(a)); } int main() { std::function<int(int)> inc = std::bind(add, std::placeholders::_1, 1); Thunk<decltype(inc), int, int> thunk(&inc); call(thunk.getPtr(), 2); }
#include <functional> #include <stdio.h> #include "xbyak/xbyak.h" void call(void (*f)()) { f(); } int main() { int a = 1; struct _ : public Xbyak::CodeGenerator { _(int *a) { push(reinterpret_cast<intptr_t>(a)); call(reinterpret_cast<void *>(run)); add(esp, 4); ret(); } static void run(int &a) { printf("%d\n", a++); } } closure(&a); auto f = reinterpret_cast<void (*)()>( const_cast<Xbyak::uint8 *>(closure.getCode())); f(); f(); call(f); }
#include <functional> #include <stdio.h> #include "xbyak/xbyak.h" template <class T> struct Thunk : public Xbyak::CodeGenerator { Thunk(T *f) { mov(ecx, reinterpret_cast<intptr_t>(f)); auto p = &T::operator(); jmp(*reinterpret_cast<void **>(&p)); } void (*getPtr())() { return reinterpret_cast<void (*)()>( const_cast<Xbyak::uint8 *>(getCode())); } }; void call(void (*f)()) { f(); } int main() { int a = 1; auto f = [&] { printf("%d\n", a++); }; f(); f(); Thunk<decltype(f)> thunk(&f); auto f2 = thunk.getPtr(); f2(); call(f2); }
ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE hInstance, int nCmdShow); LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);};
--- win32thunk.cpp.orig +++ win32thunk.cpp @@ -3,6 +3,7 @@ #include "stdafx.h" #include "win32thunk.h" +#include "xbyak/xbyak.h" #define MAX_LOADSTRING 100 @@ -12,11 +13,25 @@ TCHAR szWindowClass[MAX_LOADSTRING]; // ¥á¥¤¥ó ¥¦¥£¥ó¥É¥¦ ¥¯¥é¥¹Ì¾ // ¤³¤Î¥³¡¼¥É ¥â¥¸¥å¡¼¥ë¤Ë´Þ¤Þ¤ì¤ë´Ø¿ô¤ÎÀë¸À¤òžÁ÷¤·¤Þ¤¹: -ATOM MyRegisterClass(HINSTANCE hInstance); -BOOL InitInstance(HINSTANCE, int); -LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); +template <class T, class TA1, class TA2, class TA3, class TA4, class TR> +struct StdCallThunk : public Xbyak::CodeGenerator { + void init(T *t, TR(T::*p)(TA1, TA2, TA3, TA4)) { + mov(ecx, reinterpret_cast<intptr_t>(t)); + jmp(*reinterpret_cast<void **>(&p)); + } +}; + +class Window { +protected: + StdCallThunk<Window, HWND, UINT, WPARAM, LPARAM, LRESULT> wndProc; +public: + ATOM MyRegisterClass(HINSTANCE hInstance); + BOOL InitInstance(HINSTANCE hInstance, int nCmdShow); + LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +}; + int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, @@ -32,10 +47,11 @@ // ¥°¥í¡¼¥Ð¥ëʸ»úÎó¤ò½é´ü²½¤·¤Æ¤¤¤Þ¤¹¡£ LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_WIN32THUNK, szWindowClass, MAX_LOADSTRING); - MyRegisterClass(hInstance); + Window win; + win.MyRegisterClass(hInstance); // ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î½é´ü²½¤ò¼Â¹Ô¤·¤Þ¤¹: - if (!InitInstance (hInstance, nCmdShow)) + if (!win.InitInstance (hInstance, nCmdShow)) { return FALSE; } @@ -70,14 +86,16 @@ // Àµ¤·¤¤·Á¼°¤Î¾®¤µ¤¤¥¢¥¤¥³¥ó¤ò¼èÆÀ¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë¤Ë¤Ï¡¢ // ¤³¤Î´Ø¿ô¤ò¸Æ¤Ó½Ð¤·¤Æ¤¯¤À¤µ¤¤¡£ // -ATOM MyRegisterClass(HINSTANCE hInstance) +ATOM Window::MyRegisterClass(HINSTANCE hInstance) { + wndProc.init(this, &Window::WndProc); + WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = WndProc; + wcex.lpfnWndProc = (WNDPROC)wndProc.getCode(); wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; @@ -101,7 +119,7 @@ // ¤³¤Î´Ø¿ô¤Ç¡¢¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤Ç¥¤¥ó¥¹¥¿¥ó¥¹ ¥Ï¥ó¥É¥ë¤òÊݸ¤·¡¢ // ¥á¥¤¥ó ¥×¥í¥°¥é¥à ¥¦¥£¥ó¥É¥¦¤òºîÀ®¤ª¤è¤Óɽ¼¨¤·¤Þ¤¹¡£ // -BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +BOOL Window::InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; @@ -131,7 +149,7 @@ // WM_DESTROY - Ãæ»ß¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤·¤ÆÌá¤ë // // -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +LRESULT Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps;
--- win32thunk.cpp.orig +++ win32thunk.cpp @@ -27,6 +27,7 @@ protected: StdCallThunk<Window, HWND, UINT, WPARAM, LPARAM, LRESULT> wndProc; public: + HWND hWnd; ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE hInstance, int nCmdShow); LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); @@ -121,8 +122,6 @@ // BOOL Window::InitInstance(HINSTANCE hInstance, int nCmdShow) { - HWND hWnd; - hInst = hInstance; // ¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤Ë¥¤¥ó¥¹¥¿¥ó¥¹½èÍý¤ò³ÊǼ¤·¤Þ¤¹¡£ hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
// TODO: ¥×¥í¥°¥é¥à¤ËɬÍפÊÄɲåإåÀ¡¼¤ò¤³¤³¤Ç»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡£ +#include <list> +#include <functional> +#include "xbyak/xbyak.h"
std::list<std::function<bool(int, int)>> Command;
case WM_COMMAND: for each (auto f in Command) if (f(LOWORD(wParam), HIWORD(wParam))) return 0; return DefWindowProc(hWnd, message, wParam, lParam);
win.Command.push_back([&](int id, int e)->bool { // ÁªÂò¤µ¤ì¤¿¥á¥Ë¥å¡¼¤Î²òÀÏ: switch (id) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), win.hWnd, About); return true; case IDM_EXIT: DestroyWindow(win.hWnd); return true; } return false; });
std::list<std::function<void(HDC)>> Paint;
case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: ÉÁ²è¥³¡¼¥É¤ò¤³¤³¤ËÄɲ䷤Ƥ¯¤À¤µ¤¤... for each (auto f in Paint) f(hdc); EndPaint(hWnd, &ps); break;
win.Paint.push_back([&](HDC hdc) { auto oldPen = (HPEN)SelectObject(hdc, GetStockObject(BLACK_PEN)); auto oldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(GRAY_BRUSH)); Rectangle(hdc, 10, 10, 40, 40); SelectObject(hdc, oldPen); SelectObject(hdc, oldBrush); });
#include <windowsx.h>
std::list<std::function<void(int, int, int, WPARAM)>> MouseDown, MouseUp; std::list<std::function<void(int, int, WPARAM)>> MouseMove;
void OnMouseDown(int button, WPARAM wParam, LPARAM lParam) { int x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam); for each (auto f in MouseDown) f(button, x, y, wParam); } void OnMouseUp(int button, WPARAM wParam, LPARAM lParam) { int x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam); for each (auto f in MouseUp) f(button, x, y, wParam); }
case WM_LBUTTONDOWN: OnMouseDown(1, wParam, lParam); break; case WM_RBUTTONDOWN: OnMouseDown(2, wParam, lParam); break; case WM_MBUTTONDOWN: OnMouseDown(3, wParam, lParam); break; case WM_XBUTTONDOWN: OnMouseDown(3 + HIWORD(wParam), LOWORD(wParam), lParam); break; case WM_LBUTTONUP: OnMouseUp(1, wParam, lParam); break; case WM_RBUTTONUP: OnMouseUp(2, wParam, lParam); break; case WM_MBUTTONUP: OnMouseUp(3, wParam, lParam); break; case WM_XBUTTONUP: OnMouseUp(3 + HIWORD(wParam), LOWORD(wParam), lParam); break; case WM_MOUSEMOVE: for each (auto f in MouseMove) f(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), wParam); break;
#pragma once #include <list> #include <functional> #include <string> #include <windows.h> #include "xbyak/xbyak.h" template <class T, class TA1, class TA2, class TA3, class TA4, class TR> struct StdCallThunk : public Xbyak::CodeGenerator { void init(T *t, TR(T::*p)(TA1, TA2, TA3, TA4)) { mov(ecx, reinterpret_cast<intptr_t>(t)); jmp(*reinterpret_cast<void **>(&p)); } }; typedef std::basic_string<TCHAR> tstring; class Window { protected: HINSTANCE hInst; tstring windowClass; StdCallThunk<Window, HWND, UINT, WPARAM, LPARAM, LRESULT> wndProc; void OnMouseDown(int button, WPARAM wParam, LPARAM lParam); void OnMouseUp(int button, WPARAM wParam, LPARAM lParam); public: HWND hWnd; ATOM MyRegisterClass(HINSTANCE hInstance, const tstring &windowClass); BOOL InitInstance(const tstring &title, int nCmdShow); LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); std::list<std::function<bool(int, int)>> Command; std::list<std::function<void(HDC)>> Paint; std::list<std::function<void(int, int, int, WPARAM)>> MouseDown, MouseUp; std::list<std::function<void(int, int, WPARAM)>> MouseMove; };
#include "stdafx.h" #include "resource.h" void Window::OnMouseDown(int button, WPARAM wParam, LPARAM lParam) { int x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam); for each (auto f in MouseDown) f(button, x, y, wParam); } void Window::OnMouseUp(int button, WPARAM wParam, LPARAM lParam) { int x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam); for each (auto f in MouseUp) f(button, x, y, wParam); } // // ´Ø¿ô: Window::MyRegisterClass() // // ÌÜŪ: ¥¦¥£¥ó¥É¥¦ ¥¯¥é¥¹¤òÅÐÏ¿¤·¤Þ¤¹¡£ // // ¥³¥á¥ó¥È: // // ¤³¤Î´Ø¿ô¤ª¤è¤Ó»È¤¤Êý¤Ï¡¢'RegisterClassEx' ´Ø¿ô¤¬Äɲ䵤줿 // Windows 95 ¤è¤êÁ°¤Î Win32 ¥·¥¹¥Æ¥à¤È¸ß´¹¤µ¤»¤ë¾ì¹ç¤Ë¤Î¤ßɬÍפǤ¹¡£ // ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤¬¡¢´ØÏ¢ÉÕ¤±¤é¤ì¤¿ // Àµ¤·¤¤·Á¼°¤Î¾®¤µ¤¤¥¢¥¤¥³¥ó¤ò¼èÆÀ¤Ç¤¤ë¤è¤¦¤Ë¤¹¤ë¤Ë¤Ï¡¢ // ¤³¤Î´Ø¿ô¤ò¸Æ¤Ó½Ð¤·¤Æ¤¯¤À¤µ¤¤¡£ // ATOM Window::MyRegisterClass(HINSTANCE hInstance, const tstring &windowClass) { hInst = hInstance; this->windowClass = windowClass; wndProc.init(this, &Window::WndProc); WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)wndProc.getCode(); wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32THUNK)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WIN32THUNK); wcex.lpszClassName = windowClass.c_str(); wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } // // ´Ø¿ô: Window::InitInstance(HINSTANCE, int) // // ÌÜŪ: ¥¤¥ó¥¹¥¿¥ó¥¹ ¥Ï¥ó¥É¥ë¤òÊݸ¤·¤Æ¡¢¥á¥¤¥ó ¥¦¥£¥ó¥É¥¦¤òºîÀ®¤·¤Þ¤¹¡£ // // ¥³¥á¥ó¥È: // // ¤³¤Î´Ø¿ô¤Ç¡¢¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤Ç¥¤¥ó¥¹¥¿¥ó¥¹ ¥Ï¥ó¥É¥ë¤òÊݸ¤·¡¢ // ¥á¥¤¥ó ¥×¥í¥°¥é¥à ¥¦¥£¥ó¥É¥¦¤òºîÀ®¤ª¤è¤Óɽ¼¨¤·¤Þ¤¹¡£ // BOOL Window::InitInstance(const tstring &title, int nCmdShow) { hWnd = CreateWindow(windowClass.c_str(), title.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // ´Ø¿ô: Window::WndProc(HWND, UINT, WPARAM, LPARAM) // // ÌÜŪ: ¥á¥¤¥ó ¥¦¥£¥ó¥É¥¦¤Î¥á¥Ã¥»¡¼¥¸¤ò½èÍý¤·¤Þ¤¹¡£ // // WM_COMMAND - ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó ¥á¥Ë¥å¡¼¤Î½èÍý // WM_PAINT - ¥á¥¤¥ó ¥¦¥£¥ó¥É¥¦¤ÎÉÁ²è // WM_DESTROY - Ãæ»ß¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤·¤ÆÌá¤ë // // LRESULT Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: for each (auto f in Command) if (f(LOWORD(wParam), HIWORD(wParam))) return 0; return DefWindowProc(hWnd, message, wParam, lParam); case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: ÉÁ²è¥³¡¼¥É¤ò¤³¤³¤ËÄɲ䷤Ƥ¯¤À¤µ¤¤... for each (auto f in Paint) f(hdc); EndPaint(hWnd, &ps); break; case WM_LBUTTONDOWN: OnMouseDown(1, wParam, lParam); break; case WM_RBUTTONDOWN: OnMouseDown(2, wParam, lParam); break; case WM_MBUTTONDOWN: OnMouseDown(3, wParam, lParam); break; case WM_XBUTTONDOWN: OnMouseDown(3 + HIWORD(wParam), LOWORD(wParam), lParam); break; case WM_LBUTTONUP: OnMouseUp(1, wParam, lParam); break; case WM_RBUTTONUP: OnMouseUp(2, wParam, lParam); break; case WM_MBUTTONUP: OnMouseUp(3, wParam, lParam); break; case WM_XBUTTONUP: OnMouseUp(3 + HIWORD(wParam), LOWORD(wParam), lParam); break; case WM_MOUSEMOVE: for each (auto f in MouseMove) f(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), wParam); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
// win32thunk.cpp : ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î¥¨¥ó¥È¥ê ¥Ý¥¤¥ó¥È¤òÄêµÁ¤·¤Þ¤¹¡£ // #include "stdafx.h" #include "win32thunk.h" static tstring LoadTString(HINSTANCE hInstance, UINT uID) { const int buflen = 256; TCHAR buf[buflen]; LoadString(hInstance, uID, buf, buflen); return buf; } // ¤³¤Î¥³¡¼¥É ¥â¥¸¥å¡¼¥ë¤Ë´Þ¤Þ¤ì¤ë´Ø¿ô¤ÎÀë¸À¤òžÁ÷¤·¤Þ¤¹: INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: ¤³¤³¤Ë¥³¡¼¥É¤òÁÞÆþ¤·¤Æ¤¯¤À¤µ¤¤¡£ MSG msg; HACCEL hAccelTable; Window win; win.MyRegisterClass(hInstance, LoadTString(hInstance, IDC_WIN32THUNK)); win.Command.push_back([&](int id, int e)->bool { // ÁªÂò¤µ¤ì¤¿¥á¥Ë¥å¡¼¤Î²òÀÏ: switch (id) { case IDM_ABOUT: DialogBox(hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), win.hWnd, About); return true; case IDM_EXIT: DestroyWindow(win.hWnd); return true; } return false; }); win.Paint.push_back([&](HDC hdc) { auto oldPen = (HPEN)SelectObject(hdc, GetStockObject(BLACK_PEN)); auto oldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(GRAY_BRUSH)); Rectangle(hdc, 10, 10, 40, 40); SelectObject(hdc, oldPen); SelectObject(hdc, oldBrush); }); // ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î½é´ü²½¤ò¼Â¹Ô¤·¤Þ¤¹: if (!win.InitInstance(LoadTString(hInstance, IDS_APP_TITLE), nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32THUNK)); // ¥á¥¤¥ó ¥á¥Ã¥»¡¼¥¸ ¥ë¡¼¥×: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // ¥Ð¡¼¥¸¥ç¥ó¾ðÊó¥Ü¥Ã¥¯¥¹¤Î¥á¥Ã¥»¡¼¥¸ ¥Ï¥ó¥É¥é¡¼¤Ç¤¹¡£ INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }
POINT pb = { 10, 10 }; win.Paint.push_back([&](HDC hdc) { auto oldPen = (HPEN)SelectObject(hdc, GetStockObject(BLACK_PEN)); auto oldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(GRAY_BRUSH)); Rectangle(hdc, pb.x, pb.y, pb.x + 40, pb.y + 40); SelectObject(hdc, oldPen); SelectObject(hdc, oldBrush); }); bool sel = false; POINT pd, pb2; win.MouseDown.push_back([&](int btn, int x, int y, WPARAM) { if (pb.x <= x && x <= pb.x + 40 && pb.y <= y && y <= pb.y + 40) { pd.x = x; pd.y = y; pb2 = pb; sel = true; } }); win.MouseMove.push_back([&](int x, int y, WPARAM) { if (sel) { pb.x = pb2.x + (x - pd.x); pb.y = pb2.y + (y - pd.y); InvalidateRect(win.hWnd, nullptr, true); } }); win.MouseUp.push_back([&](int, int, int, WPARAM) { sel = false; });
int test() { return 1; return 2; return 3; }
printf("%d\n", test()); // 1 printf("%d\n", test()); // 2 printf("%d\n", test()); // 3
auto t1 = new test; printf("%d\n", t1()); // 1 printf("%d\n", t1()); // 2 auto t2 = new test; printf("%d\n", t2()); // 1
using System; using System.Collections.Generic; class Test { static IEnumerable<int> test() { yield return 1; yield return 2; yield return 3; } static void Main() { var t1 = test().GetEnumerator(); if (t1.MoveNext()) Console.WriteLine(t1.Current); if (t1.MoveNext()) Console.WriteLine(t1.Current); var t2 = test().GetEnumerator(); if (t2.MoveNext()) Console.WriteLine(t2.Current); } }
def test(): yield 1 yield 2 yield 3 t1 = test() print t1.next() print t1.next() t2 = test() print t2.next()
#include <stdio.h> #include <setjmp.h> jmp_buf jb; int main() { if (setjmp(jb) == 0) { printf("setjmp\n"); printf("test\n"); longjmp(jb, 1); printf("never reach here\n"); } printf("longjmp done.\n"); }
#include <stdio.h> #include <setjmp.h> jmp_buf jb; void test1(const char *s) { setjmp(jb); printf("&s: %p, s: %p; %s\n", &s, s, s); } void test2(int a) { printf("&a: %p, a: %d\n", &a, a); longjmp(jb, 0); } int main() { test1("test"); test2(0); printf("end\n"); }
#include <stdio.h> #include <setjmp.h> jmp_buf jb; class Test { const char *s; public: Test(const char *s) : s(s) {} ~Test() { printf("%s\n", s); } }; void test() { Test t1("t1"); longjmp(jb, 1); } int main() { Test t2("t2"); if (setjmp(jb) == 0) { Test t3("t3"); test(); } }
#include <stdio.h> #include <setjmp.h> jmp_buf jb1, jb2; int i; void test() { for (i = 1; i <= 10; i++) if (setjmp(jb2) == 0) longjmp(jb1, i); longjmp(jb1, -1); } int main() { int value = setjmp(jb1); if (value == 0) test(); else if (value > 0) { printf("%d\n", value); longjmp(jb2, 1); } }
*** ¥í¡¼¥«¥ëÊÑ¿ô
#include <setjmp.h> jmp_buf jb1, jb2; -int i; void test() { + int i; for (i = 1; i <= 10; i++) if (setjmp(jb2) == 0) longjmp(jb1, i);
*** C#
class Program { static IEnumerable<int> test() { for (int i = 1; i <= 10; i++) yield return i; } static void Main(string[] args) { foreach (var i in test()) Console.WriteLine(i); } }
#include <stdio.h> typedef struct { unsigned long eip, esp, ebp, ebx, edi, esi; } myjmp_buf; _declspec(naked) int mysetjmp(myjmp_buf *jbuf) { _asm { mov edx, [esp+4] mov eax, [esp] mov [edx ], eax mov [edx+ 4], esp mov [edx+ 8], ebp mov [edx+12], ebx mov [edx+16], edi mov [edx+20], esi xor eax, eax ret } } _declspec(naked) void mylongjmp(myjmp_buf *jbuf, int value) { _asm { mov eax, [esp+ 8] mov edx, [esp+ 4] mov ecx, [edx ] mov esp, [edx+ 4] mov ebp, [edx+ 8] mov ebx, [edx+12] mov edi, [edx+16] mov esi, [edx+20] mov [esp], ecx ret } } myjmp_buf jb; int main() { if (mysetjmp(&jb) == 0) { printf("setjmp\n"); printf("test\n"); mylongjmp(&jb, 1); printf("never reach here\n"); } printf("longjmp done.\n"); }
typedef struct { unsigned long eip, esp, ebp, ebx, edi, esi; } myjmp_buf; _declspec(naked) int _fastcall mysetjmp(myjmp_buf *jbuf) { _asm { pop edx mov [ecx ], edx mov [ecx+ 4], esp mov [ecx+ 8], ebp mov [ecx+12], ebx mov [ecx+16], edi mov [ecx+20], esi xor eax, eax jmp edx } } _declspec(naked) void _fastcall mylongjmp(myjmp_buf *jbuf, int value) { _asm { mov eax, edx mov esp, [ecx+ 4] mov ebp, [ecx+ 8] mov ebx, [ecx+12] mov edi, [ecx+16] mov esi, [ecx+20] jmp dword ptr [ecx] } }
#include <stdio.h> myjmp_buf jb1, jb2; int i, *p; void test() { for (i = 1; i <= 10; i++) if (mysetjmp(&jb2) == 0) { for (p = (int *)jb2.esp; p < (int *)jb1.esp; p++) printf("%p: %p\n", p, *p); mylongjmp(&jb1, i); } mylongjmp(&jb1, -1); } int main() { int value = mysetjmp(&jb1); if (value == 0) test(); else if (value > 0) { printf("%d\n", value); mylongjmp(&jb2, 1); } }
typedef struct { unsigned long eip, esp, ebp, ebx, edi, esi; void *stack; int length; } myjmp_buf; _declspec(naked) int _fastcall mysetjmp(myjmp_buf *jbuf) { _asm { pop edx mov [ecx ], edx mov [ecx+ 4], esp mov [ecx+ 8], ebp mov [ecx+12], ebx mov [ecx+16], edi mov [ecx+20], esi xor eax, eax mov [ecx+24], eax mov [ecx+28], eax jmp edx } } _declspec(naked) void _fastcall mylongjmp(myjmp_buf *jbuf, int value) { _asm { mov eax, edx mov edx, ecx mov esp, [edx+ 4] mov edi, esp mov esi, [edx+24] mov ecx, [edx+28] cld rep movsb mov ebp, [edx+ 8] mov ebx, [edx+12] mov edi, [edx+16] mov esi, [edx+20] jmp dword ptr [edx] } }
#include <string.h> #include <vector> void save_stack(std::vector<char> *dest, unsigned long last, myjmp_buf *callee) { callee->length = last - callee->esp; dest->resize(callee->length); callee->stack = &(*dest)[0]; memcpy(callee->stack, (void *)callee->esp, callee->length); }
#include <stdio.h> myjmp_buf jb1, jb2; std::vector<char> stack; int i, *p; void test() { for (i = 1; i <= 10; i++) if (mysetjmp(&jb2) == 0) { save_stack(&stack, jb1.esp, &jb2); for (p = (int *)jb2.esp; p < (int *)jb1.esp; p++) printf("%p: %p\n", p, *p); mylongjmp(&jb1, i); } mylongjmp(&jb1, -1); } int main() { int value = mysetjmp(&jb1); if (value == 0) test(); else if (value > 0) { printf("%d\n", value); mylongjmp(&jb2, 1); } }
myjmp_buf jb1, jb2; std::vector<char> stack; -int i, *p; +int *p; void test() { - for (i = 1; i <= 10; i++) + for (int i = 1; i <= 10; i++) if (mysetjmp(&jb2) == 0) { save_stack(&stack, jb1.esp, &jb2); for (p = (int *)jb2.esp; p < (int *)jb1.esp; p++)
#include <stdio.h> myjmp_buf jb1, jb2; std::vector<char> stack; void test() { for (int i = 1; i <= 10; i++) if (mysetjmp(&jb2) == 0) { save_stack(&stack, jb1.esp, &jb2); mylongjmp(&jb1, i); } } int main() { int value = mysetjmp(&jb1); if (value == 0) { test(); printf("end\n"); } else if (value > 0) { printf("%d\n", value); mylongjmp(&jb2, 1); } }
#include <functional> #include <vector> template <class T> class Coroutine { myjmp_buf caller, callee; std::vector<char> stack; std::function<void()> f; int status; public: T value; Coroutine() : status(0) {} Coroutine(const decltype(f) &f) : f(f), status(0) {} void operator=(const decltype(f) &f) { this->f = f; } bool operator()() { if (mysetjmp(&caller)) return true; switch (status) { case 0: status = 1; f(); status = 3; break; case 2: mylongjmp(&callee, 1); } return false; } T yield(T value) { this->value = value; if (mysetjmp(&callee) == 0) { status = 2; save_stack(&stack, caller.esp, &callee); mylongjmp(&caller, 1); } return this->value; } };
#include <stdio.h> Coroutine<int> cr; void test() { for (int i = 0; i <= 5; i++) cr.yield(i); } int main() { cr = test; while (cr()) printf("%d\n", cr.value); printf("end\n"); }
#include <functional> #include <vector> #include <stack> class CoroutineBase { public: virtual ~CoroutineBase() {} }; static std::stack<CoroutineBase *> coroutines; template <class T> class Coroutine : public CoroutineBase { myjmp_buf caller, callee; std::vector<char> stack; std::function<void()> f; int status; public: T value; Coroutine() : status(0) {} Coroutine(const decltype(f) &f) : f(f), status(0) {} void operator=(const decltype(f) &f) { this->f = f; } bool operator()() { if (mysetjmp(&caller)) return true; switch (status) { case 0: status = 1; coroutines.push(this); f(); coroutines.pop(); status = 3; break; case 2: coroutines.push(this); mylongjmp(&callee, 1); } return false; } T yield(T value) { if (coroutines.top() == this) { coroutines.pop(); status = 2; this->value = value; if (mysetjmp(&callee) == 0) { save_stack(&stack, caller.esp, &callee); mylongjmp(&caller, 1); } } return this->value; } }; template <class T> T yield(T value) { auto cr = dynamic_cast<Coroutine<T> *>(coroutines.top()); return cr ? cr->yield(value) : T(); }
#include <stdio.h> void test() { for (int i = 0; i <= 5; i++) yield(i); } int main() { Coroutine<int> cr = test; while (cr()) printf("%d\n", cr.value); printf("end\n"); }
#include <stdio.h> class Test { const char *s; public: Test(const char *s) : s(s) {} ~Test() { printf("%s\n", s); } }; void test() { Test t("test()"); for (int i = 0; i <= 5; i++) yield(i); } int main() { Test t("main()"); Coroutine<int> cr = test; while (cr()) printf("%d\n", cr.value); printf("end\n"); }
#include <stdio.h> void test() { for (int i = 0; i <= 5; i++) yield(i); printf("test: done\n"); } Coroutine<int> cr = test; void test2() { if (cr()) printf("test2: %d\n", cr.value); } int main() { if (cr()) printf("main: %d\n", cr.value); test2(); if (cr()) printf("main: %d\n", cr.value); }
template <class T> class Coroutine : public CoroutineBase { myjmp_buf caller, callee; std::vector<char> stack; - std::function<void()> f; + void (*f)(); int status; public:
#include <stdio.h> void test() { int a; printf("\r&a: %p ", &a); fflush(stdout); test(); } int main() { int a; printf("&a: %p\n", &a); test(); return 0; }
std::vector<char> stack; std::function<void()> f; int status; + unsigned long last; public: T value; Coroutine() : status(0) {} Coroutine(const decltype(f) &f) : f(f), status(0) {} void operator=(const decltype(f) &f) { this->f = f; } bool operator()() { + if (status == 0) _alloca(32 * 1024); if (mysetjmp(&caller)) return true; switch (status) { case 0: + last = caller.esp; status = 1; coroutines.push(this); f();
status = 3; break; case 2: + if (caller.esp < callee.esp) + return false; coroutines.push(this); mylongjmp(&callee, 1); }
status = 2; this->value = value; if (mysetjmp(&callee) == 0) { - save_stack(&stack, caller.esp, &callee); + save_stack(&stack, last, &callee); mylongjmp(&caller, 1); } }
#include <stdio.h> void test() { - for (int i = 0; i <= 5; i++) + for (int i = 0; i <= 0; i++) yield(i); printf("test: done\n"); }
case 0: status = 1; coroutines.push(this); f(); coroutines.pop(); status = 3; break;
int status; unsigned long last; + void exec() { + f(); + mylongjmp(&caller, 2); + } + public: T value; Coroutine() : status(0) {} Coroutine(const decltype(f) &f) : f(f), status(0) {} void operator=(const decltype(f) &f) { this->f = f; } bool operator()() { if (status == 0) _alloca(32 * 1024); - if (mysetjmp(&caller)) return true; + switch (mysetjmp(&caller)) { + case 1: + return true; + case 2: + coroutines.pop(); + status = 3; + return false; + } switch (status) { case 0: last = caller.esp; status = 1; coroutines.push(this); - f(); - coroutines.pop(); - status = 3; - break; + exec(); case 2: if (caller.esp < callee.esp) return false;
#pragma once #include <vector> #include <functional> #include <stack> typedef struct { unsigned long eip, esp, ebp, ebx, edi, esi; void *stack; int length; } myjmp_buf; extern int _fastcall mysetjmp(myjmp_buf *jbuf); extern void _fastcall mylongjmp(myjmp_buf *jbuf, int value); extern void save_stack(std::vector<char> *dest, unsigned long last, myjmp_buf *callee); class CoroutineBase { public: virtual ~CoroutineBase(); }; extern std::stack<CoroutineBase *> coroutines; template <class T> class Coroutine : public CoroutineBase { myjmp_buf caller, callee; std::vector<char> stack; std::function<void()> f; int status; unsigned long last; void exec() { f(); mylongjmp(&caller, 2); } public: T value; Coroutine() : status(0) {} Coroutine(const decltype(f) &f) : f(f), status(0) {} void operator=(const decltype(f) &f) { this->f = f; } bool operator()() { if (status == 0) _alloca(32 * 1024); switch (mysetjmp(&caller)) { case 1: return true; case 2: coroutines.pop(); status = 3; return false; } switch (status) { case 0: last = caller.esp; status = 1; coroutines.push(this); exec(); case 2: if (caller.esp < callee.esp) return false; coroutines.push(this); mylongjmp(&callee, 1); } return false; } T yield(T value) { if (coroutines.top() == this) { coroutines.pop(); status = 2; this->value = value; if (mysetjmp(&callee) == 0) { save_stack(&stack, last, &callee); mylongjmp(&caller, 1); } } return this->value; } }; template <class T> T yield(T value) { auto cr = dynamic_cast<Coroutine<T> *>(coroutines.top()); return cr ? cr->yield(value) : T(); }
#include "Coroutine.h" _declspec(naked) int _fastcall mysetjmp(myjmp_buf *jbuf) { _asm { pop edx mov [ecx ], edx mov [ecx+ 4], esp mov [ecx+ 8], ebp mov [ecx+12], ebx mov [ecx+16], edi mov [ecx+20], esi xor eax, eax mov [ecx+24], eax mov [ecx+28], eax jmp edx } } _declspec(naked) void _fastcall mylongjmp(myjmp_buf *jbuf, int value) { _asm { mov eax, edx mov edx, ecx mov esp, [edx+ 4] mov edi, esp mov esi, [edx+24] mov ecx, [edx+28] cld rep movsb mov ebp, [edx+ 8] mov ebx, [edx+12] mov edi, [edx+16] mov esi, [edx+20] jmp dword ptr [edx] } } void save_stack(std::vector<char> *dest, unsigned long last, myjmp_buf *callee) { callee->length = last - callee->esp; dest->resize(callee->length); callee->stack = &(*dest)[0]; memcpy(callee->stack, (void *)callee->esp, callee->length); } std::stack<CoroutineBase *> coroutines; CoroutineBase::~CoroutineBase() {}
#include <iostream> #include <string> #include "Coroutine.h" using namespace std; void test1() { yield<string>("abc"); yield<string>("1234"); yield<string>("finish!"); } void test2() { Coroutine<string> cr = test1; while (cr()) { auto s = cr.value; cout << s << ": "; yield<int>(s.size()); } } int main() { Coroutine<int> cr = test2; while (cr()) cout << cr.value << endl; }
#include <iostream> #include "Coroutine.h" using namespace std; void test() { int n = 0; for (;;) n = yield(++n); } int main() { Coroutine<int> cr = test; if (cr()) cout << cr.value << endl; if (cr()) cout << cr.value << endl; cr.value = 5; if (cr()) cout << cr.value << endl; }
#include <iostream> #include "Coroutine.h" using namespace std; int main() { int n = 0; Coroutine<int> cr = [&] { for (;;) yield(++n); }; if (cr()) cout << cr.value << endl; if (cr()) cout << cr.value << endl; n = 5; if (cr()) cout << cr.value << endl; }
#include <iostream> #include "Coroutine.h" using namespace std; int main() { struct Test { int n; Test() : n(0) {} void operator()() { for (;;) yield(++n); } } test; Coroutine<int> cr1 = test; if (cr1()) cout << "cr1: " << cr1.value << endl; if (cr1()) cout << "cr1: " << cr1.value << endl; Coroutine<int> cr2 = test; if (cr2()) cout << "cr2: " << cr2.value << endl; if (cr2()) cout << "cr2: " << cr2.value << endl; cout << "test.n: " << test.n << endl; }
¥³¥ë¡¼¥Á¥ó¤«¤é¤Î´Ø¿ô¸Æ¤Ó½Ð¤·¤Ç¥¹¥¿¥Ã¥¯¤¬Ç˲õ¤µ¤ì¤ë¶²¤ì¤¬¤¢¤ë¡£
¤½¤ì¤è¤ê²¼¤Ø¤Î¸Æ¤Ó½Ð¤·¤Ï¸½¹Ô¤Î¥¹¥¿¥Ã¥¯¤ò¾ÃÈñ¤µ¤»¤ë¤Î¤¬¥¹¥Þ¡¼¥È¡£
// TODO: ¥×¥í¥°¥é¥à¤ËɬÍפÊÄɲåإåÀ¡¼¤ò¤³¤³¤Ç»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡£ #include <list> #include <functional> #include <string> #include "xbyak/xbyak.h" #include "Window.h" +#include "Coroutine.h"
- #include "Coroutine.h" + #include "stdafx.h"
int mx, my; Coroutine<bool> cr = [&] { for (;;) { yield(false); int x = mx, y = my, px = pb.x, py = pb.y; while (yield(true)) { pb.x = px + (mx - x); pb.y = py + (my - y); InvalidateRect(win.hWnd, nullptr, true); } } }; cr(); win.MouseDown.push_back([&](int btn, int x, int y, WPARAM) { if (pb.x <= x && x <= pb.x + 40 && pb.y <= y && y <= pb.y + 40) { mx = x; my = y; if (!cr.value) cr(); } }); win.MouseMove.push_back([&](int x, int y, WPARAM) { if (cr.value) { mx = x; my = y; cr(); } }); win.MouseUp.push_back([&](int btn, int x, int y, WPARAM) { if (cr.value) { cr.value = false; cr(); } });
Coroutine() : status(0) {} Coroutine(const decltype(f) &f) : f(f), status(0) {} void operator=(const decltype(f) &f) { this->f = f; } + void reset() { if (status == 3) status = 0; } bool operator()() { if (status == 0) _alloca(32 * 1024);
class DragHandler { Coroutine<bool> cr; std::function<void()> handler; public: int x, y; DragHandler(Window *win) { win->MouseMove.push_back([&](int x, int y, WPARAM) { if (cr.value) { this->x = x; this->y = y; cr(); } }); win->MouseUp.push_back([&](int button, int x, int y, WPARAM) { if (cr.value) { cr.value = false; cr(); } }); } void operator=(const decltype(handler) &h) { cr = handler = h; cr.value = false; } void start(int x, int y) { this->x = x; this->y = y; if (!cr.value) { cr.reset(); cr(); } } };
DragHandler dh(&win); win.MouseDown.push_back([&](int btn, int x, int y, WPARAM) { if (pb.x <= x && x <= pb.x + 40 && pb.y <= y && y <= pb.y + 40) dh.start(x, y); }); dh = [&] { int x = dh.x, y = dh.y, px = pb.x, py = pb.y; while (yield(true)) { pb.x = px + (dh.x - x); pb.y = py + (dh.y - y); InvalidateRect(win.hWnd, nullptr, true); } };
struct Rect { int x, y, w, h; inline int r() { return x + w; } inline int b() { return y + h; } Rect(int x, int y, int w, int h): x(x), y(y), w(w), h(h) {} bool contains(int px, int py) { return x <= px && px < r() && y <= py && py < b(); } }; std::vector<Rect> rects; rects.push_back(Rect(10, 10, 40, 40)); rects.push_back(Rect(60, 60, 40, 40)); win.Paint.push_back([&](HDC hdc) { auto oldPen = (HPEN)SelectObject(hdc, GetStockObject(BLACK_PEN)); auto oldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(GRAY_BRUSH)); for (auto it = rects.begin(); it != rects.end(); it++) Rectangle(hdc, it->x, it->y, it->r(), it->b()); SelectObject(hdc, oldPen); SelectObject(hdc, oldBrush); }); DragHandler dh(&win); decltype(rects.rbegin()) sel; win.MouseDown.push_back([&](int btn, int x, int y, WPARAM) { for (auto it = rects.rbegin(); it != rects.rend(); it++) { if (it->contains(x, y)) { sel = it; dh.start(x, y); break; } } }); dh = [&] { int x = dh.x, y = dh.y, rx = sel->x, ry = sel->y; while (yield(true)) { sel->x = rx + (dh.x - x); sel->y = ry + (dh.y - y); InvalidateRect(win.hWnd, nullptr, true); } };
DragHandler dh(&win), dh2(&win); decltype(rects.rbegin()) sel; win.MouseDown.push_back([&](int btn, int x, int y, WPARAM) { for (auto it = rects.rbegin(); it != rects.rend(); it++) { if (it->contains(x, y)) { sel = it; if (it->r() - x <= 5 && it->b() - y <= 5) dh2.start(x, y); else dh.start(x, y); break; } } }); dh = [&] { int x = dh.x, y = dh.y, rx = sel->x, ry = sel->y; while (yield(true)) { sel->x = rx + (dh.x - x); sel->y = ry + (dh.y - y); InvalidateRect(win.hWnd, nullptr, true); } }; dh2 = [&] { int x = dh2.x, y = dh2.y, rw = sel->w, rh = sel->h; while (yield(true)) { sel->w = rw + (dh2.x - x); sel->h = rh + (dh2.y - y); InvalidateRect(win.hWnd, nullptr, true); } };
http://hp.vector.co.jp/authors/VA022575/c/msgmap.h...
http://code.google.com/p/libconcurrent/wiki/Projec...
http://d.hatena.ne.jp/u_1roh/20080302/1204471238