使用go语言调用DLL,简单介绍

如何使用go语言调用别人的dll,帮我介绍一下,让我能听懂。

不要做A语言代码修改为B语言代码的无用功。
也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。
只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。
即可很方便地让A、B两种语言之间协调工作。
比如:
A将请求数据写到文件a.txt,写完后改名为aa.txt
B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt
A发现bb.txt存在时,读取其内容,读完后删除bb.txt
以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。
除非A或B不支持判断文件是否存在、文件读写和文件更名。
但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢?
可以将临时文件放在RamDisk上提高效率减少磨损磁盘。
数据的结构很复杂的话,文本文件的格式问题可参考json或xml

共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多,下面仅列出我现在能想到的:
·进程之间松耦合
·进程可在同一台机器上,也可跨机,跨操作系统,跨硬件平台,甚至跨国。
·方便调试和监视,只需让第三方或人工查看该临时文本文件即可。
·方便在线开关服务,只需删除或创建该临时文本文件即可。
·方便实现分布式和负载均衡。
·方便队列化提供服务,而且几乎不可能发生队列满的情况(除非硬盘空间满)
·……

“跨语言、跨机,跨操作系统,跨硬件平台,跨国,跨*.*的”苦海无边,
回头是“使用共享纯文本文件进行信息交流”的岸!

假设我们要调用的DLL名为"mydll.dll",其中包含一个名为"myfunc"的导出函数,该函数接受一个字符串参数并返回一个字符串。
示例代码如下:

package main

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

func main() {
    dll, err := syscall.LoadLibrary("mydll.dll")
    if err != nil {
        fmt.Println("Failed to load DLL:", err)
        return
    }

    defer syscall.FreeLibrary(dll)

    myfunc, err := syscall.GetProcAddress(dll, "myfunc")
    if err != nil {
        fmt.Println("Failed to get function handle:", err)
        return
    }

    myfuncProc := syscall.NewProc(myfunc)

    input := "Hello, World!"
    var output uintptr

    ret, _, _ := myfuncProc.Call(uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(input))), uintptr(unsafe.Pointer(&output)))

    if ret != 0 {
        fmt.Println("Failed to call function:", ret)
        return
    }

    result := syscall.UTF16ToString((*[1 << 16]uint16)(unsafe.Pointer(output))[:])
    fmt.Println("Result:", result)
}

syscall/dll包

可以借鉴下

package main   import (  "syscall"  
)  func main(){  h, err := syscall.LoadLibrary("kernel32.dll")  if err != nil {  abort("LoadLibrary", err)  }  defer syscall.FreeLibrary(h)  proc, err := syscall.GetProcAddress(h, "GetVersion")  if err != nil {  abort("GetProcAddress", err)  }  r, _, _ := syscall.Syscall(uintptr(proc), 0, 0, 0, 0)  print_version(uint32(r))  
}  func abort(funcname string, err error) {  panic(funcname + " failed: " + err.Error())  
}  func print_version(v uint32) {  major := byte(v)  minor := uint8(v >> 8)  build := uint16(v >> 16)  print("windows version ", major, ".", minor, " (Build ", build, ")\n")  
}  

Go语言调用dll

    user32 := syscall.NewLazyDLL("imobiledevice.dll")
    MessageBoxW := user32.NewProc("idevice_event_subscribe")
    MessageBoxW.Call(uintptr(C.test), uintptr(s))

mobiledevice.dll为调用的dll名字
idevice_event_subscribe为dll内函数名。
通过MessageBoxW.Call调用函数,需要把参数转指针类型.

可以使用syscall包来调用DLL文件

本次回答借鉴了 GPT4

  1. 导入 "C" 和 "fmt" 包
import "C" 
import "fmt"
  1. 设置DLL函数的搜索路径。通过cgo设置CGO_LDFLAGS环境变量,例如:
CGO_LDFLAGS="-L/path/to/dll -lnameoffile"
  1. 定义 DLL 函数原型。使用 C. 函数来声明原型,例如:
// DLL function: int add(int, int);
add := C.add   
  1. 调用 DLL 函数。使用标准Go语法调用C. 函数,例如:
result := C.add(1, 2)  
fmt.Println(result)   // Prints 3
  1. 处理回调函数(可选)。如果DLL导出了接受回调函数的参数,需要在Go中定义一个兼容的回调函数,并使用unsafe.Pointer进行转换。此处略为复杂,需要单独处理。
  2. 指定导出函数(Windows)。如果在Windows上调用DLL,需要在DLL中显式导出函数,使用__declspec(dllexport)。
  3. 编译Go代码。使用 go build 进行编译,需要带上 "-ldflags='-Linker Flags...'" 参数和 "-cgo" 参数,例如:
go build -ldflags='-ldflags "-L/path/to/dll -lnameoffile"' -cgo 

在Go的知识库其实可以查到你要的答案,先分享些发你

其实,调用外部 DLL 文件可以使用 syscall 包。下面是使用 Go 语言调用外部 DLL 文件的步骤:

  1. 在 Go 中声明 DLL 函数。您需要使用 type 关键字和 func 方法定义 DLL 函数的参数和返回值类型。例如:
type MyDLLFunc func(int32) int32
  1. 打开 DLL 文件并加载它。可以使用 syscall.LoadLibrary 函数打开 DLL 文件并获得一个 handle 句柄。例如:
handle, err := syscall.LoadLibrary("mydll.dll")
if err != nil {
    panic(err)
}
defer syscall.FreeLibrary(handle)
  1. 获取 DLL 函数地址。可以使用 syscall.GetProcAddress 函数获取 DLL 函数的地址,并将返回的东西转换为 MyDLLFunc 类型。例如:
dllFuncPointer, err := syscall.GetProcAddress(handle, "myDLLFunc")
if err != nil {
    panic(err)
}
myDLLFunc := syscall.NewCallback(dllFuncPointer)
  1. 调用 DLL 函数。使用 myDLLFunc 调用函数,并传入所需的参数。例如:
result := myDLLFunc(5)
fmt.Println("Result:", result)

完整的代码如下所示:

package main

import (
    "fmt"
    "syscall"
)

type MyDLLFunc func(int32) int32

func main() {
    // 打开 DLL 文件
    handle, err := syscall.LoadLibrary("mydll.dll")
    if err != nil {
        panic(err)
    }
    defer syscall.FreeLibrary(handle)

    // 获取 DLL 函数地址
    dllFuncPointer, err := syscall.GetProcAddress(handle, "myDLLFunc")
    if err != nil {
        panic(err)
    }
    myDLLFunc := syscall.NewCallback(dllFuncPointer)

    // 调用 DLL 函数
    result := myDLLFunc(5)
    fmt.Println("Result:", result)
}

当使用Go语言调用外部DLL时,你需要进行以下步骤:

导入C语言包:使用import "C"语句导入C语言包,以便在Go代码中使用C语言的功能。

声明外部DLL函数:在Go代码中,使用//export注释来声明要调用的DLL函数。这样做可以让Go编译器生成对应的C语言函数符号,并使其可供DLL调用。

构建Go代码:使用Go工具链构建你的Go代码,生成可执行文件或动态链接库(.dll/.so文件)。

准备DLL文件:确保你的DLL文件位于正确的位置,并具有正确的名称和函数符号。你可以使用C编译器将你的C代码编译为DLL文件。

运行Go程序:运行生成的Go可执行文件或动态链接库文件,它将会调用外部DLL中的函数。

总结起来,你需要在Go代码中导入C语言包并声明要调用的DLL函数,然后使用Go工具链构建代码并准备DLL文件。最后,你可以运行生成的Go程序来调用外部DLL函数。