Golang 生成dll动态库并调用

Jackey Golang 8,971 次浏览 , 没有评论

安装gcc环境

运行环境:window10 64位

下载路径:http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/4.8.2/threads-posix/seh/x86_64-4.8.2-release-posix-seh-rt_v3-rev2.7z/download

解压缩到  C:\MinGW\mingw64 目录下, 还需要在 path 环境变量中增加 C:\MinGW\mingw64\bin 确保可以找到gcc。

编写需要生成dll的golang代码

plugin.go

  1. package main
  2.  
  3. import "C"
  4. import (
  5. "fmt"
  6. )
  7.  
  8. //export DCall
  9. func DCall() int {
  10. return 2
  11. }
  12.  
  13. //export DCallWithParam
  14. func DCallWithParam(msg *C.char) *C.char {
  15. return msg
  16. }
  17.  
  18. func main() {
  19. fmt.Println("goroute全部退出")
  20. }

执行命令生成dll文件:

  1. go build -buildmode=c-shared -o plugin.dll plugin.go

会附带生成plugin.h文件

  1. /* Code generated by cmd/cgo; DO NOT EDIT. */
  2.  
  3. /* package command-line-arguments */
  4.  
  5.  
  6. #line 1 "cgo-builtin-export-prolog"
  7.  
  8. #include <stddef.h> /* for ptrdiff_t below */
  9.  
  10. #ifndef GO_CGO_EXPORT_PROLOGUE_H
  11. #define GO_CGO_EXPORT_PROLOGUE_H
  12.  
  13. #ifndef GO_CGO_GOSTRING_TYPEDEF
  14. typedef struct { const char *p; ptrdiff_t n; } _GoString_;
  15. #endif
  16.  
  17. #endif
  18.  
  19. /* Start of preamble from import "C" comments. */
  20.  
  21.  
  22.  
  23.  
  24. /* End of preamble from import "C" comments. */
  25.  
  26.  
  27. /* Start of boilerplate cgo prologue. */
  28. #line 1 "cgo-gcc-export-header-prolog"
  29.  
  30. #ifndef GO_CGO_PROLOGUE_H
  31. #define GO_CGO_PROLOGUE_H
  32.  
  33. typedef signed char GoInt8;
  34. typedef unsigned char GoUint8;
  35. typedef short GoInt16;
  36. typedef unsigned short GoUint16;
  37. typedef int GoInt32;
  38. typedef unsigned int GoUint32;
  39. typedef long long GoInt64;
  40. typedef unsigned long long GoUint64;
  41. typedef GoInt64 GoInt;
  42. typedef GoUint64 GoUint;
  43. typedef __SIZE_TYPE__ GoUintptr;
  44. typedef float GoFloat32;
  45. typedef double GoFloat64;
  46. typedef float _Complex GoComplex64;
  47. typedef double _Complex GoComplex128;
  48.  
  49. /*
  50.   static assertion to make sure the file is being used on architecture
  51.   at least with matching size of GoInt.
  52. */
  53. typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];
  54.  
  55. #ifndef GO_CGO_GOSTRING_TYPEDEF
  56. typedef _GoString_ GoString;
  57. #endif
  58. typedef void *GoMap;
  59. typedef void *GoChan;
  60. typedef struct { void *t; void *v; } GoInterface;
  61. typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
  62.  
  63. #endif
  64.  
  65. /* End of boilerplate cgo prologue. */
  66.  
  67. #ifdef __cplusplus
  68. extern "C" {
  69. #endif
  70.  
  71.  
  72. extern GoInt DCall();
  73.  
  74. extern char* DCallWithParam(char* p0);
  75.  
  76. #ifdef __cplusplus
  77. }
  78. #endif

Golang代码调用

pluginLoad.go

  1. package main
  2.  
  3. import "C"
  4. import (
  5. "fmt"
  6. "syscall"
  7. "unsafe"
  8. )
  9.  
  10. func main() {
  11. dll := syscall.NewLazyDLL("plugin.dll")
  12. f := dll.NewProc("DCall")
  13. res, _, _ := f.Call()
  14. fmt.Println(res)
  15.  
  16. f2 := dll.NewProc("DCallWithParam")
  17. r, _, _ := f2.Call(uintptr(unsafe.Pointer(syscall.StringBytePtr("php2.cc"))))
  18. // 获取C返回的指针。
  19. // 注意C返回的r为char*,对应的Go类型为*byte
  20. p := (*byte)(unsafe.Pointer(r))
  21. // 定义一个[]byte切片,用来存储C返回的字符串
  22. data := make([]byte, 0)
  23. // 遍历C返回的char指针,直到 '\0' 为止
  24. for *p != 0 {
  25. data = append(data, *p) // 将得到的byte追加到末尾
  26. r += unsafe.Sizeof(byte(0)) // 移动指针,指向下一个char
  27. p = (*byte)(unsafe.Pointer(r)) // 获取指针的值,此时指针已经指向下一个char
  28. }
  29. name := string(data) // 将data转换为字符串
  30.  
  31. fmt.Printf("Hello, %s!\n", name)
  32. }

域名命令:

  1. go run pluginLoad.go

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Go