Archive for the ‘Go’ Category

  1. Hello, Win32 GUI(Go) World!

    Posted on 7月 21st, 2012 by cx20

    Win32 GUI(Go)

    Win32 アプリケーションは Windows 標準 API である Win32 API を使用した Windows アプリケーションである。
    以下は Go言語 における Win32 GUI アプリケーション の例となっている。

    ソースコード

    package main
     
    import (
        "syscall"
        "unsafe"
    )
     
    const (
        WS_OVERLAPPED   = 0x00000000
        WS_POPUP        = 0x80000000
        WS_CHILD        = 0x40000000
        WS_MINIMIZE     = 0x20000000
        WS_VISIBLE      = 0x10000000
        WS_DISABLED     = 0x08000000
        WS_CLIPSIBLINGS = 0x04000000
        WS_CLIPCHILDREN = 0x02000000
        WS_MAXIMIZE     = 0x01000000
        WS_CAPTION      = 0x00C00000 // WS_BORDER | WS_DLGFRAME
        WS_BORDER       = 0x00800000
        WS_DLGFRAME     = 0x00400000
        WS_VSCROLL      = 0x00200000
        WS_HSCROLL      = 0x00100000
        WS_SYSMENU      = 0x00080000
        WS_THICKFRAME   = 0x00040000
        WS_GROUP        = 0x00020000
        WS_TABSTOP      = 0x00010000
     
        WS_MINIMIZEBOX  = 0x00020000
        WS_MAXIMIZEBOX  = 0x00010000
     
        WS_TILED        = WS_OVERLAPPED
        WS_ICONIC       = WS_MINIMIZE
        WS_SIZEBOX      = WS_THICKFRAME
        WS_TILEDWINDOW  = WS_OVERLAPPEDWINDOW
     
        WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
        WS_POPUPWINDOW  = WS_POPUP | WS_BORDER | WS_SYSMENU
        WS_CHILDWINDOW  = WS_CHILD
     
        WM_CREATE       = 0x0001
        WM_DESTROY      = 0x0002
        WM_PAINT        = 0x000F
        WM_CLOSE        = 0x0010
        WM_COMMAND      = 0x0111
     
        COLOR_WINDOW    = 5
        COLOR_BTNFACE   = 15
     
        CS_VREDRAW      = 0x0001
        CS_HREDRAW      = 0x0002
     
        CW_USEDEFAULT   = -2147483648 // ((int)0x80000000)
     
        SW_SHOWDEFAULT  = 10
    )
     
    type WNDCLASSEX struct {
        cbSize         uint32
        style          uint32
        lpfnWndProc    uintptr
        cbClsExtra     int32
        cbWndExtra     int32
        hInstance      syscall.Handle
        hIcon          syscall.Handle
        hCursor        syscall.Handle
        hbrBackground  syscall.Handle
        lpszMenuName   *uint16
        lpszClassName  *uint16
        hIconSm        syscall.Handle
    }
     
    type POINT struct {
        x uintptr
        y uintptr
    }
     
    type MSG struct {
        hWnd    syscall.Handle
        message uint32
        wParam  uintptr
        lParam  uintptr
        time    uint32
        pt      POINT
    }
     
    type RECT struct {
        Left int32
        Top  int32
        Right int32
        Bottom  int32
    }
     
    type PAINTSTRUCT struct {
        hdc syscall.Handle
        fErace uint32
        rcPaint RECT
        fRestore uint32
        fIncUpdate uint32
        rgbReserved byte
    }
     
    var (
        kernel32, _ = syscall.LoadLibrary("kernel32.dll")
        user32, _   = syscall.LoadLibrary("user32.dll")
        gdi32, _    = syscall.LoadLibrary("gdi32.dll")
     
        procGetModuleHandleW, _ = syscall.GetProcAddress(kernel32, "GetModuleHandleW")
        procLoadIconW, _        = syscall.GetProcAddress(user32, "LoadIconW")
        procLoadCursorW, _      = syscall.GetProcAddress(user32, "LoadCursorW")
        procRegisterClassExW, _ = syscall.GetProcAddress(user32, "RegisterClassExW")
        procCreateWindowExW, _  = syscall.GetProcAddress(user32, "CreateWindowExW")
        procDefWindowProcW, _   = syscall.GetProcAddress(user32, "DefWindowProcW")
        procDestroyWindow, _    = syscall.GetProcAddress(user32, "DestroyWindow")
        procPostQuitMessage, _  = syscall.GetProcAddress(user32, "PostQuitMessage")
        procShowWindow, _       = syscall.GetProcAddress(user32, "ShowWindow")
        procUpdateWindow, _     = syscall.GetProcAddress(user32, "UpdateWindow")
        procGetMessageW, _      = syscall.GetProcAddress(user32, "GetMessageW")
        procTranslateMessage, _ = syscall.GetProcAddress(user32, "TranslateMessage")
        procDispatchMessageW, _ = syscall.GetProcAddress(user32, "DispatchMessageW")
        procSendMessageW, _     = syscall.GetProcAddress(user32, "SendMessageW")
        procPostMessageW, _     = syscall.GetProcAddress(user32, "PostMessageW")
        procBeginPaint, _       = syscall.GetProcAddress(user32, "BeginPaint")
        procEndPaint, _         = syscall.GetProcAddress(user32, "EndPaint")
        procTextOutW, _         = syscall.GetProcAddress(gdi32, "TextOutW")
     
        IDC_ARROW = MakeIntResource(32512)
        IDI_APPLICATION = MakeIntResource(32512)
    )
     
    func GetModuleHandle(lpModuleName *uint16) (syscall.Handle) {
        ret, _, _ := syscall.Syscall(uintptr(procGetModuleHandleW), 1, uintptr(unsafe.Pointer(lpModuleName)), 0, 0)
        return syscall.Handle(ret)
    }
     
    func LoadIcon(instance syscall.Handle, iconname *uint16) (syscall.Handle) {
        ret, _, _ := syscall.Syscall(uintptr(procLoadIconW), 2, uintptr(instance), uintptr(unsafe.Pointer(iconname)), 0)
        return syscall.Handle(ret)
    }
     
    func LoadCursor(instance syscall.Handle, cursorname *uint16) (syscall.Handle) {
        ret, _, _ := syscall.Syscall(uintptr(procLoadCursorW), 2, uintptr(instance), uintptr(unsafe.Pointer(cursorname)), 0)
        return syscall.Handle(ret)
    }
     
    func RegisterClassEx(lpwcx *WNDCLASSEX) (uint16) {
        ret, _, _ := syscall.Syscall(uintptr(procRegisterClassExW), 1, uintptr(unsafe.Pointer(lpwcx)), 0, 0)
        return uint16(ret)
     
    }
     
    func CreateWindowEx(dwExStyle uint32, lpClassName *uint16, lpWindowName *uint16, dwStyle uint32, x int32, y int32, nWidth int32, nHeight int32, hWndParent syscall.Handle, hMenu syscall.Handle, hInstance syscall.Handle, lpParam uintptr) (syscall.Handle) {
        ret, _, _ := syscall.Syscall12(uintptr(procCreateWindowExW), 12, uintptr(dwExStyle), uintptr(unsafe.Pointer(lpClassName)), uintptr(unsafe.Pointer(lpWindowName)), uintptr(dwStyle), uintptr(x), uintptr(y), uintptr(nWidth), uintptr(nHeight), uintptr(hWndParent), uintptr(hMenu), uintptr(hInstance), uintptr(lpParam))
        return syscall.Handle(ret)
    }
     
    func DefWindowProc(hWnd syscall.Handle, Msg uint32, wParam uintptr, lParam uintptr) (uintptr) {
        ret, _, _ := syscall.Syscall6(uintptr(procDefWindowProcW), 4, uintptr(hWnd), uintptr(Msg), uintptr(wParam), uintptr(lParam), 0, 0)
        return uintptr(ret)
    }
     
    func DestroyWindow(hWnd syscall.Handle) {
        syscall.Syscall(uintptr(procDestroyWindow), 1, uintptr(hWnd), 0, 0)
        return
    }
     
    func PostQuitMessage(nExitCode int32) {
        syscall.Syscall(uintptr(procPostQuitMessage), 1, uintptr(nExitCode), 0, 0)
        return
    }
     
    func ShowWindow(hWnd syscall.Handle, nCmdShow int32) (bool) {
        ret, _, _ := syscall.Syscall(uintptr(procShowWindow), 2, uintptr(hWnd), uintptr(nCmdShow), 0)
        return bool(ret != 0)
    }
     
    func UpdateWindow(hWnd syscall.Handle) {
        syscall.Syscall(uintptr(procUpdateWindow), 1, uintptr(hWnd), 0, 0)
        return
    }
     
    func GetMessage(lpMsg *MSG, hWnd syscall.Handle, wMsgFilterMin uint32, wMsgFilterMax uint32) (int32) {
        ret, _, _ := syscall.Syscall6(uintptr(procGetMessageW), 4, uintptr(unsafe.Pointer(lpMsg)), uintptr(hWnd), uintptr(wMsgFilterMin), uintptr(wMsgFilterMax), 0, 0)
        return int32(ret)
    }
     
    func TranslateMessage(lpMsg *MSG) (bool) {
        r, _, _ := syscall.Syscall(uintptr(procTranslateMessage), 1, uintptr(unsafe.Pointer(lpMsg)), 0, 0)
        return bool(r != 0)
    }
     
    func DispatchMessage(lpMsg *MSG) (int32) {
        ret, _, _ := syscall.Syscall(uintptr(procDispatchMessageW), 1, uintptr(unsafe.Pointer(lpMsg)), 0, 0)
        return int32(ret)
    }
     
    func SendMessage(hWnd syscall.Handle, Msg uint32, wParam uintptr, lParam uintptr) (uintptr) {
        ret, _, _ := syscall.Syscall6(uintptr(procSendMessageW), 4, uintptr(hWnd), uintptr(Msg), uintptr(wParam), uintptr(lParam), 0, 0)
        return uintptr(ret)
    }
     
    func PostMessage(hWnd syscall.Handle, Msg uint32, wParam uintptr, lParam uintptr) {
        syscall.Syscall6(uintptr(procPostMessageW), 4, uintptr(hWnd), uintptr(Msg), uintptr(wParam), uintptr(lParam), 0, 0)
        return
    }
     
    func BeginPaint(hDC syscall.Handle, lpPaint *PAINTSTRUCT ) (syscall.Handle) {
        ret, _, _ := syscall.Syscall(uintptr(procBeginPaint), 2, uintptr(hDC), uintptr(unsafe.Pointer(lpPaint)), 0)
        return syscall.Handle(ret)
    }
     
    func EndPaint(hDC syscall.Handle, lpPaint *PAINTSTRUCT ) (syscall.Handle) {
        ret, _, _ := syscall.Syscall(uintptr(procEndPaint), 2, uintptr(hDC), uintptr(unsafe.Pointer(lpPaint)), 0)
        return syscall.Handle(ret)
    }
     
    func TextOut(hDC syscall.Handle, x int32, y int32, text string, cbString int32 ) (bool) {
        ret, _, _ := syscall.Syscall6(uintptr(procTextOutW), 5, uintptr(hDC), uintptr(x), uintptr(y), uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text))), uintptr(cbString), 0)
        return bool(ret != 0)
    }
     
    func MakeIntResource(id uint16) (*uint16) {
        return (*uint16)(unsafe.Pointer(uintptr(id)))
    }
     
    func WndProc(hWnd syscall.Handle, msg uint32, wParam, lParam uintptr) (uintptr) {
        switch msg {
        case WM_PAINT:
            var strMessage = "Hello, Win32 GUI(Go) World!"
            var ps PAINTSTRUCT
            hdc := BeginPaint(hWnd, &ps)
            TextOut( hdc, 0, 0, strMessage, int32(len(strMessage)) )
            EndPaint( hWnd, &ps )
        case WM_DESTROY:
            PostQuitMessage(0)
        default:
            return DefWindowProc(hWnd, msg, wParam, lParam)
        }
        return 0
    }
     
    func WinMain() int {
        hInstance := GetModuleHandle(nil)
        lpszClassName := syscall.StringToUTF16Ptr("helloWindow")
        lpszWindowName := syscall.StringToUTF16Ptr("Hello, World!")
        var wcex WNDCLASSEX
        wcex.cbSize        = uint32(unsafe.Sizeof(wcex))
        wcex.style         = CS_HREDRAW | CS_VREDRAW
        wcex.lpfnWndProc   = syscall.NewCallback(WndProc)
        wcex.cbClsExtra    = 0
        wcex.cbWndExtra    = 0
        wcex.hInstance     = hInstance
        wcex.hIcon         = LoadIcon(hInstance, IDI_APPLICATION)
        wcex.hCursor       = LoadCursor(0, IDC_ARROW)
        wcex.hbrBackground = COLOR_WINDOW + 1
        wcex.lpszMenuName  = nil
        wcex.lpszClassName = lpszClassName
        wcex.hIconSm       = LoadIcon(hInstance, IDI_APPLICATION)
        RegisterClassEx(&wcex)
     
        hWnd := CreateWindowEx(
            0,
            lpszClassName,
            lpszWindowName,
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
            0, 0, hInstance, 0)
     
        ShowWindow(hWnd, SW_SHOWDEFAULT)
        UpdateWindow(hWnd)
     
        var msg MSG
        for {
            if GetMessage(&msg, 0, 0, 0) == 0 {
                break
            }
            TranslateMessage(&msg)
            DispatchMessage(&msg)
        }
        return int(msg.wParam)
    }
     
    func main() {
        WinMain()
        return
    }

    コンパイル方法

    C:¥> SET GOROOT=C:go
    C:¥> go build -ldflags -Hwindowsgui hello.go

    実行結果

    +------------------------------------------+
    |Hello, World!                    [_][~][X]|
    +------------------------------------------+
    |Hello, Win32 GUI(Go) World!               |
    |                                          |
    |                                          |
    |                                          |
    |                                          |
    |                                          |
    |                                          |
    |                                          |
    |                                          |
    |                                          |
    +------------------------------------------+
  2. Hello, COM(Go) World!

    Posted on 5月 31st, 2012 by cx20

    COM(Go)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は Go言語 による COM クライアントの例となっている。

    ソースコード

    package main
     
    import (
        "syscall" 
        "unsafe" 
    )
     
    const (
        CLSCTX_INPROC_SERVER   = 1
        CLSCTX_LOCAL_SERVER    = 4
     
        DISPATCH_METHOD        = 1
        DISPATCH_PROPERTYGET   = 2
        DISPATCH_PROPERTYPUT   = 4
     
        VT_EMPTY           = 0x0
        VT_NULL            = 0x1
        VT_I2              = 0x2
        VT_I4              = 0x3
        VT_R4              = 0x4
        VT_R8              = 0x5
        VT_CY              = 0x6
        VT_DATE            = 0x7
        VT_BSTR            = 0x8
        VT_DISPATCH        = 0x9
        VT_ERROR           = 0xa
        VT_BOOL            = 0xb
        VT_VARIANT         = 0xc
        VT_UNKNOWN         = 0xd
        VT_DECIMAL         = 0xe
        VT_I1              = 0x10
        VT_UI1             = 0x11
        VT_UI2             = 0x12
        VT_UI4             = 0x13
        VT_I8              = 0x14
        VT_UI8             = 0x15
        VT_INT             = 0x16
        VT_UINT            = 0x17
        VT_VOID            = 0x18
        VT_VECTOR          = 0x1000
        VT_ARRAY           = 0x2000
        VT_BYREF           = 0x4000
        VT_RESERVED        = 0x8000
    )
     
    type DISPPARAMS struct {
        rgvarg              uintptr
        rgdispidNamedArgs   uintptr
        cArgs               uint32
        cNamedArgs          uint32
    }
     
    type VARIANT struct {
        VT                  uint16
        wReserved1          uint16
        wReserved2          uint16
        wReserved3          uint16
        Val                 int64
    }
     
    type GUID struct {
        Data1               uint32
        Data2               uint16
        Data3               uint16
        Data4               [8]byte
    }
     
    type IDispatch struct {
        lpVtbl *pIDispatchVtbl
    }
     
    type pIDispatchVtbl struct {
        pQueryInterface     uintptr
        pAddRef             uintptr
        pRelease            uintptr
        pGetTypeInfoCount   uintptr
        pGetTypeInfo        uintptr
        pGetIDsOfNames      uintptr
        pInvoke             uintptr
    }
     
    var ( 
        ole32, _                  = syscall.LoadLibrary("ole32.dll")
        oleaut32, _               = syscall.LoadLibrary("oleaut32.dll")
        kernel32, _               = syscall.LoadLibrary("kernel32.dll")
     
        procCoInitialize, _       = syscall.GetProcAddress(ole32, "CoInitialize")
        procCoUninitialize, _     = syscall.GetProcAddress(ole32, "CoUninitialize")
        procCoCreateInstance, _   = syscall.GetProcAddress(ole32, "CoCreateInstance")
        procCLSIDFromProgID, _    = syscall.GetProcAddress(ole32, "CLSIDFromProgID")
     
        procVariantInit, _        = syscall.GetProcAddress(oleaut32, "VariantInit")
        procSysAllocString, _     = syscall.GetProcAddress(oleaut32, "SysAllocString")
        procSysFreeString, _      = syscall.GetProcAddress(oleaut32, "SysFreeString")
     
        procGetUserDefaultLCID, _ = syscall.GetProcAddress(kernel32, "GetUserDefaultLCID")
     
        IID_NULL                  = &GUID{ 0x00000000, 0x0000, 0x0000, [8]byte{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
        IID_IDispatch             = &GUID{ 0x00020400, 0x0000, 0x0000, [8]byte{ 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }
    )
     
    func CoInitialize(p uintptr) (hr uintptr) {
        hr, _, _ = syscall.Syscall(uintptr(procCoInitialize), 1, p, 0, 0)
        return
    }
     
    func CoUninitialize() {
        syscall.Syscall(uintptr(procCoUninitialize), 0, 0, 0, 0)
    }
     
    func CLSIDFromProgID(progId string) (clsid *GUID, hr uintptr) {
        var guid GUID
        hr, _, _ = syscall.Syscall( uintptr(procCLSIDFromProgID), 2,
            uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(progId))),
            uintptr(unsafe.Pointer(&guid)), 0)
        clsid = &guid
        return
    }
     
    func CreateInstance(clsid *GUID, iid *GUID) (unk *IDispatch, hr uintptr) {
        hr, _, _ = syscall.Syscall6( uintptr(procCoCreateInstance), 5,
            uintptr(unsafe.Pointer(clsid)),
            0,
            CLSCTX_INPROC_SERVER,
            uintptr(unsafe.Pointer(iid)),
            uintptr(unsafe.Pointer(&unk)),
            0)
        return
    }
     
    func (disp *IDispatch) GetIDsOfNames(names []string) (dispid []int32, hr uintptr) {
        wnames := make([]*uint16, len(names))
        for i := 0; i < len(names); i++ {
            wnames[i] = syscall.StringToUTF16Ptr(names[i])
        }
        dispid = make([]int32, len(names))
        hr, _, _ = syscall.Syscall6( disp.lpVtbl.pGetIDsOfNames, 6,
            uintptr(unsafe.Pointer(disp)),
            uintptr(unsafe.Pointer(IID_NULL)),
            uintptr(unsafe.Pointer(&wnames[0])),
            uintptr(len(names)),
            uintptr(GetUserDefaultLCID()),
            uintptr(unsafe.Pointer(&dispid[0])) )
        return
    }
     
    func (disp *IDispatch) Invoke(dispid int32, dispatch int16, params ...interface{}) (result *VARIANT, hr uintptr) {
        var dispparams DISPPARAMS
        var vargs []VARIANT
        if len(params) > 0 {
            vargs = make([]VARIANT, len(params))
            for i, v := range params {
                n := len(params) - i - 1
                VariantInit(&vargs[n])
                switch v.(type) {
                case bool:
                    if v.(bool) {
                        vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0xffff}
                    } else {
                        vargs[n] = VARIANT{VT_BOOL, 0, 0, 0, 0}
                    }
                case int16:
                    vargs[n] = VARIANT{VT_I2, 0, 0, 0, int64(v.(int16))}
                case float32:
                    vargs[n] = VARIANT{VT_R4, 0, 0, 0, int64(v.(float32))}
                case float64:
                    vargs[n] = VARIANT{VT_R8, 0, 0, 0, int64(v.(float64))}
                case byte:
                    vargs[n] = VARIANT{VT_I1, 0, 0, 0, int64(v.(byte))}
                case uint16:
                    vargs[n] = VARIANT{VT_UI2, 0, 0, 0, int64(v.(int16))}
                case int, int32:
                    vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(int))}
                case uint, uint32:
                    vargs[n] = VARIANT{VT_UI4, 0, 0, 0, int64(v.(uint))}
                case string:
                    vargs[n] = VARIANT{VT_BSTR, 0, 0, 0, int64(uintptr(unsafe.Pointer(SysAllocString(v.(string)))))}
                case *IDispatch:
                    vargs[n] = VARIANT{VT_DISPATCH, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))}
                case *bool:
                    vargs[n] = VARIANT{VT_BOOL | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*bool))))}
                case *byte:
                    vargs[n] = VARIANT{VT_I1 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*byte))))}
                case *int16:
                    vargs[n] = VARIANT{VT_I2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int16))))}
                case *uint16:
                    vargs[n] = VARIANT{VT_UI2 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint16))))}
                case *int, *int32:
                    vargs[n] = VARIANT{VT_I4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*int))))}
                case *uint, *uint32:
                    vargs[n] = VARIANT{VT_UI4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*uint))))}
                case *float32:
                    vargs[n] = VARIANT{VT_R4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float32))))}
                case *float64:
                    vargs[n] = VARIANT{VT_R8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float64))))}
                case *string:
                    vargs[n] = VARIANT{VT_BSTR | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*string))))}
                case **IDispatch:
                    vargs[n] = VARIANT{VT_DISPATCH | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))}
                case *VARIANT:
                    vargs[n] = VARIANT{VT_VARIANT | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))}
                case nil:
                    vargs[n] = VARIANT{VT_NULL, 0, 0, 0, 0}
                default:
                    panic("unknown type")
                }
            }
            dispparams.rgvarg = uintptr(unsafe.Pointer(&vargs[0]))
            dispparams.cArgs = uint32(len(params))
        }
     
        result = new(VARIANT)
        VariantInit(result)
        hr, _, _ = syscall.Syscall9( disp.lpVtbl.pInvoke, 9,
            uintptr(unsafe.Pointer(disp)),
            uintptr(dispid),
            uintptr(unsafe.Pointer(IID_NULL)),
            uintptr(GetUserDefaultLCID()),
            uintptr(dispatch),
            uintptr(unsafe.Pointer(&dispparams)),
            uintptr(unsafe.Pointer(result)),
            0,
            0)
        for _, varg := range vargs {
            if varg.VT == VT_BSTR && varg.Val != 0 {
                SysFreeString(((*int16)(unsafe.Pointer(uintptr(varg.Val)))))
            }
        }
        return
    }
     
    func GetUserDefaultLCID() (lcid uint32) {
        ret, _, _ := syscall.Syscall(uintptr(procGetUserDefaultLCID), 0, 0, 0, 0)
        lcid = uint32(ret)
        return
    }
     
    func VariantInit(v *VARIANT) (hr uintptr) {
        hr, _, _ = syscall.Syscall( uintptr(procVariantInit), 1, uintptr(unsafe.Pointer(v)), 0, 0)
        return
    }
     
    func SysAllocString(v string) (ss *int16) {
        pss, _, _ := syscall.Syscall( uintptr(procSysAllocString), 1, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(v))), 0, 0)
        ss = (*int16)(unsafe.Pointer(pss))
        return
    }
     
    func SysFreeString(v *int16) (hr uintptr) {
        hr, _, _ = syscall.Syscall( uintptr(procSysFreeString), 1, uintptr(unsafe.Pointer(v)), 0, 0)
        return
    }
     
    func main() {
        CoInitialize(0)
     
        clsid, _ := CLSIDFromProgID("Shell.Application")
        disp, _ := CreateInstance(clsid, IID_IDispatch)
        dispid, _ := disp.GetIDsOfNames([]string{"BrowseForFolder"})
        disp.Invoke(dispid[0], DISPATCH_METHOD, 0, "Hello, COM(Go) World!", 0, 36)
     
        CoUninitialize()
    }

    実行方法

    C:¥> go build hello.go

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(Go) Wolrd!                  |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  3. Hello, Win32 API(Go) World!

    Posted on 5月 6th, 2012 by cx20

    Win32 API(Go)

    Win32 API は、Windows の機能にアクセスする為の API(Application Programming Interface)である。
    以下は Go言語 にて syscall.Syscall 関数を用いた呼出し例である。

    ソースコード

    package main 
     
    import ( 
        "syscall" 
        "unsafe" 
    ) 
     
    var ( 
        user32, _          = syscall.LoadLibrary("user32.dll") 
        procMessageBoxW, _ = syscall.GetProcAddress(user32, "MessageBoxW") 
    )
     
    func MessageBox(hwnd uintptr, text string, caption string, style uintptr) (int32) { 
        ret, _, _ := syscall.Syscall6(
            uintptr(procMessageBoxW), 
            4, 
            hwnd,
            uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(text))), 
            uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(caption))), 
            style, 
            0,
            0 ) 
        return int32(ret)
    } 
     
    func main() { 
        defer syscall.FreeLibrary(user32) 
        MessageBox( 0, "Hello, Win32 API(Go) World!", "Hello, World!", 0 )
    }

    Win32 データ型と Go言語 データ型の対応は主に以下のようになっている。

    Win32 データ型 C/C++ データ型 Go データ型
    HANDLE void * uintptr
    BYTE unsigned char uint8, byte
    SHORT short int16
    WORD unsigned short uint16
    INT int int32, int
    UINT unsigned int uint32
    LONG long int32
    BOOL int int
    DWORD unsigned long uint32
    ULONG unsigned long uint32
    CHAR char byte
    WCHAR wchar_t uint16
    LPSTR char * *byte
    LPCSTR const char * *byte, syscall.StringByPtr()
    LPWSTR wchar_t * *uint16
    LPCWSTR const wchar_t * *uint16, syscall.StringToUTF16Ptr()
    FLOAT float float32
    DOUBLE double float64
    LONGLONG __int64 int64
    DWORD64 unsigned __int64 uint64

    コンパイル方法

    C:¥> SET GOROOT=C:go
    C:¥> go build -ldflags -Hwindowsgui hello.go

    実行結果

    ---------------------------
    Hello, World!
    ---------------------------
    Hello, Win32 API(Go) World!
    ---------------------------
    OK   
    ---------------------------
  4. Hello, Go World!

    Posted on 12月 10th, 2011 by cx20

    Go言語

    Go言語は Google によって開発された並列コンピューティングに対応したプログラミング言語である。
    プログラムは Go言語 のオフィシャルサイト(http://golang.org/)にて試すことができる。また、このサーバー自体が Go言語 で記述されている。

    ソースコード

    package main
     
    import "fmt"
     
    func main() {
        fmt.Printf( "Hello, Go World!n" );
    }

    コンパイル&リンク方法(Go言語x64版)

    $ 6g hello.go
    $ 6l -o hello hello.6
    

    コンパイル&リンク方法(Go言語x86版)

    $ 8g hello.go
    $ 8l -o hello hello.8
    

    2012年3月に version 1 がリリースされ、コンパイル方法も以下のように変更された。

    コンパイル方法

    $ go build -o hello hello.go
    

    実行結果

    Hello, Go World!