1、dll 和 golang 的编译架构要一直,32位对应32位,64位对应64位,比如如果dll是32位的,而golang是64位的,可能会报错%1 is not a valid Win32 application.
2、有时候存在类型转换,需要开启CGO,比如,如果dll中的函数返回一个字符串,那么返回值是一个字符串指针,还需要将返回值转换成go字符串
import "C"
str := C.GoString((*C.Char)(unsafe.Pointer(ret)))
3、传入dll函数的参数被要求是 uintptr 类型,因此需要做转换。
func IntPtr(n int) uintptr {
return uintptr(n)
}
func Int2IntPtr(n int) uintptr {
return uintptr(unsafe.Pointer(&n))
}
func IntPtr2Ptr(n *int) uintptr {
return uintptr(unsafe.Pointer(n))
}
func BytePtr(s []byte) uintptr {
return uintptr(unsafe.Pointer(&s[0]))
}
func StrPtr(s string) uintptr {
return uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(s)))
}
package main
import (
"fmt"
"syscall"
)
// 设置console模式下标准输出的字体前景色
var f = "SetConsoleTextAttribute"
func main() {
f1()
f2()
f3()
f4()
}
func f1() {
// A LazyDLL implements access to a single DLL.
// It will delay the load of the DLL until the first
// call to its Handle method or to one of its
// LazyProc's Addr method.
//
// LazyDLL is subject to the same DLL preloading attacks as documented
// on LoadDLL.
//
// Use LazyDLL in golang.org/x/sys/windows for a secure way to
// load system DLLs.
dll := syscall.NewLazyDLL("kernel32.dll")
p := dll.NewProc(f)
r1, r2, lastError := p.Call(uintptr(syscall.Stdout), uintptr(3))
fmt.Println(r1, r2, lastError)
}
func f2() {
// LoadDLL loads the named DLL file into memory.
//
// If name is not an absolute path and is not a known system DLL used by
// Go, Windows will search for the named DLL in many locations, causing
// potential DLL preloading attacks.
//
// Use LazyDLL in golang.org/x/sys/windows for a secure way to
// load system DLLs.
dll, _ := syscall.LoadDLL("kernel32.dll")
p, _ := dll.FindProc(f)
r1, r2, lastError := p.Call(uintptr(syscall.Stdout), uintptr(4))
fmt.Println(r1, r2, lastError)
}
func f3() {
// MustLoadDLL is like LoadDLL but panics if load operation fails.
dll := syscall.MustLoadDLL("kernel32.dll")
p := dll.MustFindProc(f)
r1, r2, lastError := p.Call(uintptr(syscall.Stdout), uintptr(5))
fmt.Println(r1, r2, lastError)
}
func f4() {
handle, _ := syscall.LoadLibrary("kernel32.dll")
defer syscall.FreeLibrary(handle)
p, _ := syscall.GetProcAddress(handle, f)
r1, r2, errorNo := syscall.Syscall(p, 2, uintptr(syscall.Stdout), uintptr(6), 0)
fmt.Println(r1, r2, errorNo)
// 恢复到白色
syscall.Syscall(p, 2, uintptr(syscall.Stdout), uintptr(7), 0)
}