Created
December 6, 2013 07:45
-
-
Save klutzy/7820031 to your computer and use it in GitHub Desktop.
Rust with Emscripten and win32.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// From rust get `libstd/libc.rs` to the working dir. | |
// From rust-windows <https://github.com/klutzy/rust-windows> | |
// copy whole `ll/` dir to the working dir and | |
// patch some code: (TODO) | |
// From win32.js <https://github.com/klutzy/win32.js>, copy | |
// `library_win32.js` and `window.js` to working dir. | |
// | |
// emscripten uses le32-unknown-nacl triple but rustc doesn't know it now. | |
// So just use similar target instead. | |
// Here I use `win32` because libc.rs needs it. | |
// `rustc hello.rs --target=i686-unknown-win32 --emit-llvm -S` | |
// `emcc hello.js hello.ll --js-library library_win32.js --pre-js window.js` | |
#[no_std]; | |
#[feature(macro_rules, globs)]; | |
pub mod option { | |
pub enum Option<T> { | |
None, | |
Some(T), | |
} | |
} | |
pub mod ptr { | |
pub fn mut_null<T>() -> *mut T { | |
unsafe { super::transmute(0) } | |
} | |
pub fn null<T>() -> *T { | |
unsafe { super::transmute(0) } | |
} | |
} | |
pub mod libc; | |
pub mod std { | |
pub mod libc { | |
pub use super::super::libc::*; | |
} | |
} | |
pub mod ll { | |
pub use self::platform::*; | |
pub use self::windef::*; | |
pub use self::all::*; | |
pub use self::font::*; | |
pub mod platform; | |
pub mod windef; | |
pub mod all; | |
pub mod font; | |
} | |
extern "rust-intrinsic" { | |
pub fn transmute<A, B>(a: A) -> B; | |
} | |
// win32.js-specific | |
extern "C" { | |
fn emscripten_win32_loop(); | |
} | |
unsafe fn as_ptr(a: &[u16]) -> *u16 { | |
let (a, _b): (*u16, uint) = transmute(a); | |
a | |
} | |
pub static WS_CHILD: u32 = 0x40000000; | |
pub static WS_OVERLAPPEDWINDOW: u32 = 0xcf0000; | |
pub static WS_VISIBLE: u32 = 0x10000000; | |
pub static HELLO: &'static [u16] = &[0x48u16, 0x45u16, 0x4cu16, 0x4cu16, 0x4fu16, 0x0u16]; | |
pub static EDIT: &'static [u16] = &[0x45u16, 0x44u16, 0x49u16, 0x54u16, 0x0u16]; | |
pub static BUTTON: &'static [u16] = &[0x42u16, 0x55u16, 0x54u16, 0x54u16, 0x4fu16, 0x4eu16, 0x0u16]; | |
pub static cls_name: &'static [u16] = &[0x48u16, 0x65u16, 0x6cu16, 0x6cu16, 0x6fu16, 0x0u16]; // Hello | |
// TODO TLS | |
extern "stdcall" fn wnd_proc(wnd: ll::HWND, msg: ll::UINT, wparam: ll::WPARAM, lparam: ll::LPARAM) -> ll::c_long { | |
unsafe { | |
match msg { | |
0x0001 => { // WM_CREATE | |
return 0; | |
} | |
0x0111 => { // WM_COMMAND | |
if wparam & 0xFF == 101 { | |
let msg = [0, ..100]; | |
//ll::GetWindowText(hello_edit, as_ptr(msg), 100); | |
ll::MessageBoxW(wnd, as_ptr(HELLO), as_ptr(HELLO), 0); | |
} | |
} | |
0x000F => { // WM_PAINT | |
let rgb_res: [ll::BYTE, ..32] = [0 as ll::BYTE, ..32]; | |
let ps = ll::PAINTSTRUCT { | |
hdc: ptr::mut_null(), | |
fErase: 0 as ll::BOOL, | |
rcPaint: ll::RECT { | |
left: 0 as ll::LONG, top: 0 as ll::LONG, | |
right: 0 as ll::LONG, bottom: 0 as ll::LONG, | |
}, | |
fRestore: 0 as ll::BOOL, | |
fIncUpdate: 0 as ll::BOOL, | |
rgbReserved: &rgb_res, | |
}; | |
let hdc = ll::BeginPaint(wnd, &ps); | |
ll::TextOutW(hdc, 100, 300, transmute(as_ptr(HELLO)), 8); | |
ll::EndPaint(wnd, &ps); | |
return 0; | |
} | |
0x0002 => { // WM_DESTROY | |
ll::PostQuitMessage(0); | |
return 0; | |
} | |
_ => { | |
} | |
} | |
ll::DefWindowProcW(wnd, msg, wparam, lparam) | |
} | |
} | |
unsafe fn WinMain(inst: ll::HINSTANCE, _: ll::HINSTANCE, cmd_line: *u8, cmd_show: libc::c_int) { | |
let cls_p = as_ptr(cls_name); | |
let cls = ll::WNDCLASS { | |
style: 0, | |
lpfnWndProc: wnd_proc as *ll::c_void, | |
cbClsExtra: 0, | |
cbWndExtra: 0, | |
hInstance: inst, | |
hIcon: ptr::mut_null(), | |
hCursor: ptr::mut_null(), | |
hbrBackground: ptr::mut_null(), | |
lpszMenuName: ptr::null(), | |
lpszClassName: cls_p, | |
}; | |
let _res = ll::RegisterClassW(&cls); | |
let main_win = ll::CreateWindowExW(0, cls_p, cls_p, WS_OVERLAPPEDWINDOW, | |
-1, -1, 700, 500, ptr::mut_null(), ptr::mut_null(), inst, ptr::mut_null()); | |
let hello_edit = ll::CreateWindowExW(0, as_ptr(EDIT), cls_p, | |
WS_CHILD | WS_VISIBLE, 0, 0, 100, 30, main_win, ptr::mut_null(), inst, ptr::mut_null()); | |
let hello_button = ll::CreateWindowExW(0, as_ptr(BUTTON), cls_p, | |
WS_CHILD | WS_VISIBLE, 120, 0, 100, 30, main_win, transmute(101), inst, ptr::mut_null()); | |
ll::ShowWindow(main_win, cmd_show); | |
emscripten_win32_loop(); | |
} | |
fn main() { | |
unsafe { WinMain(ptr::mut_null(), ptr::mut_null(), ptr::null(), 0); } | |
} | |
#[lang="start"] | |
fn start(_: *u8, _: int, _: **u8) -> int { | |
main(); | |
0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment