Golang 调用DLL库[开箱可用][支持指针传参]
1.环境
vs2013+go1.13
x86dll文件
2.运行
go_dll.exe
3.编译
vs2013:
重新生成解决方案
\cpp_dll\Debug\cpp_dll.dll
goland:
Mac:
CGO_ENABLED=1 GOOS=windows GOARCH=386 go build main.go
Windows:
SET CGO_ENABLED=1
SET GOOS=windows
SET GOARCH=386
go build main.go
4.1 普通传参
golang核心代码
func GoCallDll1(a, b int) uintptr {
dllFile := syscall.NewLazyDLL(dllFileName)
fmt.Println("dll:", dllFile.Name)
add := dllFile.NewProc("add")
fmt.Println("+++++++NewProc:", add, "+++++++")
ret, _, err := add.Call(IntPtr(a), IntPtr(b))
if err != nil && IsFinishError(err) {
fmt.Println(dllFileName+fmt.Sprintf(":%d+%d", a, b)+"运算结果为:", ret)
} else {
fmt.Println(fmt.Sprintf("%+v", err))
}
return ret
}
func GoCallDll2(a, b int) uintptr {
dllFile, _ := syscall.LoadLibrary(dllFileName)
fmt.Println("+++++++syscall.LoadLibrary:", dllFile, "+++++++")
defer syscall.FreeLibrary(dllFile)
add, err := syscall.GetProcAddress(dllFile, "add")
fmt.Println("GetProcAddress", add)
ret, _, err := syscall.Syscall(add,
2,
IntPtr(a),
IntPtr(b),
0)
if err != nil && IsFinishError(err) {
fmt.Println(dllFileName+fmt.Sprintf(":%d+%d", a, b)+"运算结果为:", ret)
} else {
fmt.Println(fmt.Sprintf("%+v", err))
}
return ret
}
func GoCallDll3(a, b int) uintptr {
DllTestDef := syscall.MustLoadDLL(dllFileName)
add := DllTestDef.MustFindProc("add")
fmt.Println("+++++++MustFindProc:", add, "+++++++")
ret, _, err := add.Call(IntPtr(a), IntPtr(b))
if err != nil && IsFinishError(err) {
fmt.Println(dllFileName+fmt.Sprintf(":%d+%d", a, b)+"结果为:", ret)
} else {
fmt.Println(fmt.Sprintf("%+v", err))
}
return ret
}
4.2 指针传参(回参) (推荐回调函数使用)
c++代码片
extern "C" __declspec(dllexport) void * point(void *ctx){
printf("ctx:%p\n", ctx);
return ctx;
}
golang代码片
func GoCallDllPoint(c *CPoint) uintptr {
DllTestDef := syscall.MustLoadDLL(dllFileName)
point := DllTestDef.MustFindProc("point")
fmt.Println("+++++++MustFindProc:", point, "+++++++")
ret, _, err := point.Call(uintptr(unsafe.Pointer(c)))
if err != nil && IsFinishError(err) {
p := (*CPoint)(unsafe.Pointer(ret))
fmt.Println(dllFileName+fmt.Sprintf("原始:%p", c)+",运算结果为:", fmt.Sprintf("%p", p))
} else {
fmt.Println(fmt.Sprintf("%+v", err))
}
return ret
}
5.github地址
github
6.issue
1.内存泄漏:
如果强行在DLL方法中操作Golang的指针,会导致内存泄漏...暂时无法解决