概述
以下举例程序的效果是会弹出消息框。
四种方式
方式 1-立即加载
func LoadDll() {
user32Dll, err := syscall.LoadLibrary("user32.dll")
if err != nil {
panic(err)
}
// 获取dll里的函数
proc, err := syscall.GetProcAddress(user32Dll, "MessageBoxW")
if err != nil {
panic(err)
}
// 宽字节
fromString, err := syscall.UTF16PtrFromString("你好世界")
if err != nil {
panic(err)
}
// https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-messageboxw
// 参数和返回值,见上面地址
r1, _, _ := syscall.SyscallN(proc,
0,
uintptr(unsafe.Pointer(fromString)), // 因为syscalN适配所有类型的调用,所以统一转这个类型
uintptr(unsafe.Pointer(fromString)),
0,
)
if int(r1) == 1 {
fmt.Println("用户点击了确定")
}
}
方式 2-懒加载
func LoadDll2() {
u32Dll := syscall.NewLazyDLL("user32.dll")
proc := u32Dll.NewProc("MessageBoxW")
// 宽字节
fromString, err := syscall.UTF16PtrFromString("你好世界")
if err != nil {
panic(err)
}
r1, _, _ := proc.Call(
0,
uintptr(unsafe.Pointer(fromString)), // 因为syscalN适配所有类型的调用,所以统一转这个类型
uintptr(unsafe.Pointer(fromString)),
0,
)
if int(r1) == 1 {
fmt.Println("用户点击了确定")
}
r0, _, _ := syscall.SyscallN(proc.Addr(),
0,
uintptr(unsafe.Pointer(fromString)), // 因为syscalN适配所有类型的调用,所以统一转这个类型
uintptr(unsafe.Pointer(fromString)),
0,
)
if int(r0) == 1 {
fmt.Println("用户点击了确定")
}
}
方式 3-对第 1 种的封装
func LoadDll3() {
u32dll, err := syscall.LoadDLL("user32.dll")
if err != nil {
panic(err)
}
proc, err := u32dll.FindProc("MessageBoxW")
// 宽字节
fromString, err := syscall.UTF16PtrFromString("你好世界")
if err != nil {
panic(err)
}
r1, _, _ := proc.Call(
0,
uintptr(unsafe.Pointer(fromString)), // 因为syscalN适配所有类型的调用,所以统一转这个类型
uintptr(unsafe.Pointer(fromString)),
0,
)
if int(r1) == 1 {
fmt.Println("用户点击了确定")
}
r0, _, _ := syscall.SyscallN(proc.Addr(),
0,
uintptr(unsafe.Pointer(fromString)), // 因为syscalN适配所有类型的调用,所以统一转这个类型
uintptr(unsafe.Pointer(fromString)),
0,
)
if int(r0) == 1 {
fmt.Println("用户点击了确定")
}
}
方式 4-使用 windows 包
需要安装 go get golang.org/x/sys/windows
,实际上是对 NewLazyDLL 的封装,用起来很方便
func LoadDll4() {
u32Dll := windows.NewLazySystemDLL("user32.dll")
proc := u32Dll.NewProc("MessageBoxW")
// 宽字节
fromString, err := syscall.UTF16PtrFromString("你好世界")
if err != nil {
panic(err)
}
r1, _, _ := proc.Call(
0,
uintptr(unsafe.Pointer(fromString)), // 因为syscalN适配所有类型的调用,所以统一转这个类型
uintptr(unsafe.Pointer(fromString)),
0,
)
if int(r1) == 1 {
fmt.Println("用户点击了确定")
}
r0, _, _ := syscall.SyscallN(proc.Addr(),
0,
uintptr(unsafe.Pointer(fromString)), // 因为syscalN适配所有类型的调用,所以统一转这个类型
uintptr(unsafe.Pointer(fromString)),
0,
)
if int(r0) == 1 {
fmt.Println("用户点击了确定")
}
}