Golang經過syscall調用win32的Api

What you are wasting today is tomorrow for those who died yesterday; what you hate now is the future you can not go back.golang

你所浪費的今天是昨天死去的人奢望的明天; 你所厭惡的如今是將來的你回不去的曾經。 windows

 Golang不是徹底的跨平臺, 並無提供Windows下的相關方法,只能經過Syscall包去調用Win庫。api

開始

    若是你不瞭解Windows下API調用,請觀看MSDN文檔,我知道有些人找不到,不要緊:ui

1. 英文版: https://msdn.microsoft.com/en-us/library/windows/desktop/hh447209(v=vs.85)spa

2. 中文版本:http://www.office-cn.net/t/api/api_content.htm操作系統

(僅做參考,還有其餘中文版本就不一一列舉了).net

Golang syscall包

syscall包下面有5個關於系統調用的方法,分別表示調用參數的個數。 (golang文檔上可能沒有,請查詢其餘文檔或直接在IDE中查看)指針

func Syscall(trap, nargs, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
func Syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
func Syscall9(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
func Syscall12(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2 uintptr, err Errno)
func Syscall15(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2 uintptr, err Errno)

第二個參數, nargs 即參數的個數,一旦傳錯, 輕則調用失敗,重者直接崩潰 多餘的參數, 用0代替。code

小實例

    獲取磁盤的空間orm

package main

import (
	"syscall"
	"unsafe"
	"fmt"
)

func main(){
	getDiskGreeSpace()
}

/**
獲取磁盤空間
 */
func getDiskGreeSpace(){
	// 磁盤
	diskName := "E:"
	diskNameUtf16Ptr , _:= syscall.UTF16PtrFromString(diskName)
	// 一下參數類型須要跟API 的類型相符
	lpFreeBytesAvailable ,lpTotalNumberOfBytes,
	lpTotalNumberOfFreeBytes := int64(0),int64(0),int64(0)

	// 獲取方法引用
	kernel32 , err := syscall.LoadLibrary("kernel32.dll")
	if err != nil{
		panic("獲取方法引用失敗:")
	}
	// 釋放引用
	defer syscall.FreeLibrary(kernel32)


	getDisFreeSpaceEx , err := syscall.GetProcAddress(kernel32, "GetDiskFreeSpaceExW")
	if err != nil{
		panic("失敗1")
	}

	// 根據參數個數使用對象SyscallN方法, 只須要4個參數
	r , _ , errno := syscall.Syscall6(uintptr(getDisFreeSpaceEx), 4,
			uintptr(unsafe.Pointer(diskNameUtf16Ptr)), //
			uintptr(unsafe.Pointer(&lpFreeBytesAvailable)),
			uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)),
			uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)),
			0, 0)
	// 此處的errno不是error接口, 而是type Errno uintptr
	// MSDN GetDiskFreeSpaceEx function 文檔說明:
	// Return value
	// 		If the function succeeds, the return value is nonzero.
	// 		If the function fails, the return value is zero (0). To get extended error information, call GetLastError.
	// 只要是0 就是錯誤
	if  r!= 0{
		fmt.Printf("剩餘空間 %d M.\n", lpFreeBytesAvailable/1024/1204)
		fmt.Printf("用戶可用總空間 %d G.\n", lpTotalNumberOfBytes/1024/1204/1024)
		fmt.Printf("剩餘空間2 %d M.\n", lpTotalNumberOfFreeBytes/1024/1204)
	}else{
		fmt.Println("失敗2")
		panic(errno)
	}
}

首先現將MSDN官方的文檔貼出來,方便一下解釋:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa364937(v=vs.85)

BOOL WINAPI GetDiskFreeSpaceEx(
  _In_opt_  LPCTSTR         lpDirectoryName,
  _Out_opt_ PULARGE_INTEGER lpFreeBytesAvailable,
  _Out_opt_ PULARGE_INTEGER lpTotalNumberOfBytes,
  _Out_opt_ PULARGE_INTEGER lpTotalNumberOfFreeBytes
);

解釋:

1. 將磁盤的名稱轉爲*UTF16類型,

 LPCTSTR類型:

L表示long指針 這是爲了兼容Windows 3.1等16位操做系統遺留下來的,在win32中以及其餘的32位操做系統中, long指針和near指針及far修飾符都是爲了兼容的做用。沒有實際意義。

P表示這是一個指針

C表示是一個常量

T表示在Win32環境中, 有一個_T宏

STR表示這個變量是一個字符串

這是瞭解一下就行了。

2.  PULARGE_INTEGER 是存儲了64位數據的一種類型。

3. GetProcAddress中GetDiskFreeSpaceExW多了一個W具體是啥意思呢?請留言

簡單記錄一下,要熟悉MSDN API 文檔可能寫起來順手多了。

相關文章
相關標籤/搜索