[Go实战]CGO 入门系列-手把手教程2 dll动态库调用

932 阅读2分钟

CGO 入门系列-手把手教程2 dll动态库调用

接上文:

CGO 入门系列-手把手教程1

相信你已经初步了解了cgo的用法和用处 现在讲讲如何支持或扩展cpp和c的代码 dll动态库

go调用DLL

目前go支持三种方法调用:

syscall.NewLazyDLL
syscall.LoadLibrary
syscall.MustLoadDLL

go具体实现DLL调用:

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
}

c++项目:暴露三个方法提供给DLL

#include "stdafx.h"
#include <stdio.h>

extern "C" __declspec(dllexport) int add(int a, int b)
{
   return (a + b);
}

extern "C" __declspec(dllexport) int sub(int a, int b)
{
   return (a - b);
}

extern "C" __declspec(dllexport) void * point(void *ctx){
   printf("ctx:%p\n", ctx);
   return ctx;
}

运行报错:

报错问题:

# cgo
cc1.exe: sorry, unimplemented: 64-bit mode not compiled in

解决:

解决方案1:goland启动设置

CGO_ENABLED=1;GOOS=windows;GOARCH=386

图片.png

解决方案2:环境设置(win/linux)

Windows:
SET CGO_ENABLED=1
SET GOOS=windows
SET GOARCH=386
go build -o server.exe main.go

Linux:
SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build -o server main.go

运行结果:

图片.png

github项目地址:

github.com/zld126126/M…

未完待续…