Golang如何调用windows下的dll动态库中的函数

 更新时间:2021年05月06日 09:45:33   作者:uxff  
这篇文章主要介绍了Golang如何调用windows下的dll动态库中的函数方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

使用syscall调用

package main
import (
    "fmt"
    "syscall"
    "time"
    "unsafe"
)
const (
    MB_OK                = 0x00000000
    MB_OKCANCEL          = 0x00000001
    MB_ABORTRETRYIGNORE  = 0x00000002
    MB_YESNOCANCEL       = 0x00000003
    MB_YESNO             = 0x00000004
    MB_RETRYCANCEL       = 0x00000005
    MB_CANCELTRYCONTINUE = 0x00000006
    MB_ICONHAND          = 0x00000010
    MB_ICONQUESTION      = 0x00000020
    MB_ICONEXCLAMATION   = 0x00000030
    MB_ICONASTERISK      = 0x00000040
    MB_USERICON          = 0x00000080
    MB_ICONWARNING       = MB_ICONEXCLAMATION
    MB_ICONERROR         = MB_ICONHAND
    MB_ICONINFORMATION   = MB_ICONASTERISK
    MB_ICONSTOP          = MB_ICONHAND
    MB_DEFBUTTON1 = 0x00000000
    MB_DEFBUTTON2 = 0x00000100
    MB_DEFBUTTON3 = 0x00000200
    MB_DEFBUTTON4 = 0x00000300
)
func abort(funcname string, err syscall.Errno) {
    panic(funcname + " failed: " + err.Error())
}
var (
    //    kernel32, _        = syscall.LoadLibrary("kernel32.dll")
    //    getModuleHandle, _ = syscall.GetProcAddress(kernel32, "GetModuleHandleW")
    user32, _     = syscall.LoadLibrary("user32.dll")
    messageBox, _ = syscall.GetProcAddress(user32, "MessageBoxW")
)
func IntPtr(n int) uintptr {
    return uintptr(n)
}
func StrPtr(s string) uintptr {
    return uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(s)))
}
func MessageBox(caption, text string, style uintptr) (result int) {
    ret, _, callErr := syscall.Syscall9(messageBox,
        4,
        0,
        StrPtr(text),
        StrPtr(caption),
        style,
        0, 0, 0, 0, 0)
    if callErr != 0 {
        abort("Call MessageBox", callErr)
    }
    result = int(ret)
    return
}
//func GetModuleHandle() (handle uintptr) {
//    if ret, _, callErr := syscall.Syscall(getModuleHandle, 0, 0, 0, 0); callErr != 0 {
//        abort("Call GetModuleHandle", callErr)
//    } else {
//        handle = ret
//    }
//    return
//}
// windows下的第二种DLL方法调用
func ShowMessage2(title, text string) {
    user32 := syscall.NewLazyDLL("user32.dll")
    MessageBoxW := user32.NewProc("MessageBoxW")
    MessageBoxW.Call(IntPtr(0), StrPtr(text), StrPtr(title), IntPtr(0))
}
func main() {
    //    defer syscall.FreeLibrary(kernel32)
    defer syscall.FreeLibrary(user32)
    //fmt.Printf("Retern: %d\n", MessageBox("Done Title", "This test is Done.", MB_YESNOCANCEL))
    num := MessageBox("Done Title", "This test is Done.", MB_YESNOCANCEL)
    fmt.Printf("Get Retrun Value Before MessageBox Invoked: %d\n", num)
    ShowMessage2("windows下的第二种DLL方法调用", "HELLO !")
    time.Sleep(3 * time.Second)
}
func init() {
    fmt.Print("Starting Up\n")
}

补充:go 调用windows dll 的三种方法

第三种方法是从Go\src\internal\syscall\windows\sysdll源码中找到的,三种方法的具体区别还不是很明晰,

初步判断:lazy应该是相当于动态库,其余两种直接把库加载到内存。

package main
import(
	"fmt"
	"syscall"
	"time"
    "unsafe"
)
const (
    MB_OK                = 0x00000000
    MB_OKCANCEL          = 0x00000001
    MB_ABORTRETRYIGNORE  = 0x00000002
    MB_YESNOCANCEL       = 0x00000003
    MB_YESNO             = 0x00000004
    MB_RETRYCANCEL       = 0x00000005
    MB_CANCELTRYCONTINUE = 0x00000006
    MB_ICONHAND          = 0x00000010
    MB_ICONQUESTION      = 0x00000020
    MB_ICONEXCLAMATION   = 0x00000030
    MB_ICONASTERISK      = 0x00000040
    MB_USERICON          = 0x00000080
    MB_ICONWARNING       = MB_ICONEXCLAMATION
    MB_ICONERROR         = MB_ICONHAND
    MB_ICONINFORMATION   = MB_ICONASTERISK
    MB_ICONSTOP          = MB_ICONHAND
 
    MB_DEFBUTTON1 = 0x00000000
    MB_DEFBUTTON2 = 0x00000100
    MB_DEFBUTTON3 = 0x00000200
    MB_DEFBUTTON4 = 0x00000300
)
 
func abort(funcname string, err syscall.Errno) {
    panic(funcname + " failed: " + err.Error())
}
 
var (
   
    user32, _     = syscall.LoadLibrary("user32.dll")
    messageBox, _ = syscall.GetProcAddress(user32, "MessageBoxW")
)
 
func IntPtr(n int) uintptr {
    return uintptr(n)
}
 
func StrPtr(s string) uintptr {
    return uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(s)))
}
 
func MessageBox(caption, text string, style uintptr) (result int) {
    ret, _, callErr := syscall.Syscall9(messageBox,
        4,
        0,
        StrPtr(text),
        StrPtr(caption),
        style,
        0, 0, 0, 0, 0)
    if callErr != 0 {
        abort("Call MessageBox", callErr)
    }
    result = int(ret)
    return
}
 
//func GetModuleHandle() (handle uintptr) {
//    if ret, _, callErr := syscall.Syscall(getModuleHandle, 0, 0, 0, 0); callErr != 0 {
//        abort("Call GetModuleHandle", callErr)
//    } else {
//        handle = ret
//    }
//    return
//}
 
// windows下的第二种DLL方法调用
func ShowMessage2(title, text string) {
    user32 := syscall.NewLazyDLL("user32.dll")
    MessageBoxW := user32.NewProc("MessageBoxW")
    MessageBoxW.Call(IntPtr(0), StrPtr(text), StrPtr(title), IntPtr(0))
} 
 
// windows下的第三种DLL方法调用
func ShowMessage3(title, text string) {
    user32,_ := syscall.LoadDLL("user32.dll")
    MessageBoxW,_ := user32.FindProc("MessageBoxW")
    MessageBoxW.Call(IntPtr(0), StrPtr(text), StrPtr(title), IntPtr(0))
}
 
func main() {
    defer syscall.FreeLibrary(user32)
 
    num := MessageBox("Done Title", "This test is Done.", MB_YESNOCANCEL)
    fmt.Printf("Get Retrun Value Before MessageBox Invoked: %d\n", num)
    ShowMessage2("windows下的另一种DLL方法调用", "HELLO !")
	
	ShowMessage3("windows下的第三种DLL方法调用", "lyslyslys !")
 
    time.Sleep(3 * time.Second)
}
 
func init() {
    fmt.Print("Starting Up\n")
}
 
​

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

相关文章

  • golang RWMutex读写锁实现读共享写独占的功能示例

    golang RWMutex读写锁实现读共享写独占的功能示例

    在 Go 里除了互斥锁外,还有读写锁 RWMutex,它主要用来实现读共享,写独占的功能,今天我们也顺便分析下读写锁,加深对 Go 锁的理解
    2023-09-09
  • go doudou开发单体RESTful服务快速上手教程

    go doudou开发单体RESTful服务快速上手教程

    这篇文章主要为大家介绍了go doudou开发单体RESTful服务快速上手教程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • Go语言区别于其他语言的特性

    Go语言区别于其他语言的特性

    在本文中,今天这篇文章将给大家介绍一下 Go 与其他语言不同的 9 个特性,需要的朋友可以参考下面文章的具体内容
    2021-10-10
  • 手把手带你走进Go语言之语法基础解析

    手把手带你走进Go语言之语法基础解析

    这篇文章主要介绍了手把手带你走进Go语言之语法基础,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • Go 语言json.Unmarshal 遇到的小问题(推荐)

    Go 语言json.Unmarshal 遇到的小问题(推荐)

    这篇文章主要介绍了 Go 语言json.Unmarshal 遇到的小问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • 浅谈Go语言多态的实现与interface使用

    浅谈Go语言多态的实现与interface使用

    如果大家系统的学过C++、Java等语言以及面向对象的话,相信应该对多态不会陌生。多态是面向对象范畴当中经常使用并且非常好用的一个功能,它主要是用在强类型语言当中,像是Python这样的弱类型语言,变量的类型可以随意变化,也没有任何限制,其实区别不是很大
    2021-06-06
  • go使用net/url包来解析URL提取主机部分

    go使用net/url包来解析URL提取主机部分

    这篇文章主要为大家介绍了go使用net/url包来解析URL提取主机部分实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • Golang截取字符串方法示例讲解及对比

    Golang截取字符串方法示例讲解及对比

    这篇文章主要介绍了Golang截取字符串方法,文中介绍了使用rune函数和utf包以及range遍历的方式,熟练掌握这些可以帮助我们更方便地处理字符串,提高编程效率和代码质量,感兴趣的同学可以参考下文
    2023-05-05
  • Go 的入口函数和包初始化的使用

    Go 的入口函数和包初始化的使用

    本文主要介绍了Go 的入口函数和包初始化的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • Go Gin实现文件上传下载的示例代码

    Go Gin实现文件上传下载的示例代码

    这篇文章主要介绍了Go Gin实现文件上传下载的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04

最新评论