准备工作
Go需要1.10版本,即支持动态链接库
基本调用代码
lib := syscall.NewLazyDLL("lib/plugin.dll") // 读取dll
f := lib.NewProc("Sum") // 调用dll函数
res, _, _ := f.Call(param) // 传值
fmt.Println(res)
可能出现的问题
%1 is not a valid Win32 application
这是由于调用的dll位数和系统版本位数不一致导致的,需要设置成与dll位数相同的编译环境,在cmd中使用以下命令
go env // 查看set GOARCH,如果系统是64位,则等于amd64,如果是32,则是386
go env -w GOARCH=386 // 设置32编译环境
go env -w GOARCH=amd64 // 设置64编译环境
The specified module could not be found
这个问题分为三种情况
dll路径不对
调整路径即可
dll依赖别的dll,依赖的dll缺失了
下载DependenciesGui,
https://github.com/lucasg/Dependencies
打开后,菜单栏点击file->open,选择需要查看的dll
当出现红色感叹号时,则说明缺失这个dll,就需要将这个缺失的dll放在与选择的dll同目录,解决后
这个dll本身有依赖的dll,且dll与依赖dll在同一目录,但是go业务代码与dll,被依赖的dll不在同一目录,
把dll,被依赖的所有dll与业务代码放在同一目录
数据类型问题
当传值或者接收值时,f.Call(param)。所有值的类型应该都是uintptr,应该注意数据类型的转换,以下代码仅做参考:
// string到uintptr.
func StrPtr(s string) uintptr {
p, _ := syscall.UTF16PtrFromString(s)
return uintptr(unsafe.Pointer(p))
}
// uintptr到string.
func PtrStr(p uintptr) string {
return syscall.UTF16ToString(*(*[]uint16)(unsafe.Pointer(&p)))
}
// bool到uintptr.
func BoolPtr(b bool) uintptr {
if b {
return uintptr(1)
}
return uintptr(0)
}
// float32到uintptr.
func Float32Ptr(f float32) uintptr {
return uintptr(*(*uint32)(unsafe.Pointer(&f)))
}
// uintptr到float32.
func PtrToFloat32(p uintptr) float32 {
u := uint32(p)
return *(*float32)(unsafe.Pointer(&u))
}
// int到uintptr
func IntPtr(i int) uintptr {
return uintptr(i)
}
// int到uintptr
func PtrInt(u uintptr) int {
return int(u)
}
示例代码
package main
import (
"fmt"
"syscall"
)
var (
ta = syscall.NewLazyDLL("AIO_API.dll")
taInit3 = ta.NewProc("TA_Init3")
taConsume = ta.NewProc("TA_Consume")
)
func main() {
aio()
}
func aio() {
str := StrPtr("str")
i := IntPtr(123)
b := BoolPtr(true)
// 调用接口示例
res, _, _ := taConsume.Call(str, i, b)
fmt.Printf("%v", IntPtr(res))
}
目录结构