安装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
- package main
-
- import "C"
- import (
- "fmt"
- )
-
- //export DCall
- func DCall() int {
- return 2
- }
-
- //export DCallWithParam
- func DCallWithParam(msg *C.char) *C.char {
- return msg
- }
-
- func main() {
- fmt.Println("goroute全部退出")
- }
执行命令生成dll文件:
- go build -buildmode=c-shared -o plugin.dll plugin.go
会附带生成plugin.h文件
- /* Code generated by cmd/cgo; DO NOT EDIT. */
-
- /* package command-line-arguments */
-
-
- #line 1 "cgo-builtin-export-prolog"
-
- #include <stddef.h> /* for ptrdiff_t below */
-
- #ifndef GO_CGO_EXPORT_PROLOGUE_H
- #define GO_CGO_EXPORT_PROLOGUE_H
-
- #ifndef GO_CGO_GOSTRING_TYPEDEF
- typedef struct { const char *p; ptrdiff_t n; } _GoString_;
- #endif
-
- #endif
-
- /* Start of preamble from import "C" comments. */
-
-
-
-
- /* End of preamble from import "C" comments. */
-
-
- /* Start of boilerplate cgo prologue. */
- #line 1 "cgo-gcc-export-header-prolog"
-
- #ifndef GO_CGO_PROLOGUE_H
- #define GO_CGO_PROLOGUE_H
-
- typedef signed char GoInt8;
- typedef unsigned char GoUint8;
- typedef short GoInt16;
- typedef unsigned short GoUint16;
- typedef int GoInt32;
- typedef unsigned int GoUint32;
- typedef long long GoInt64;
- typedef unsigned long long GoUint64;
- typedef GoInt64 GoInt;
- typedef GoUint64 GoUint;
- typedef __SIZE_TYPE__ GoUintptr;
- typedef float GoFloat32;
- typedef double GoFloat64;
- typedef float _Complex GoComplex64;
- typedef double _Complex GoComplex128;
-
- /*
- static assertion to make sure the file is being used on architecture
- at least with matching size of GoInt.
- */
- typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];
-
- #ifndef GO_CGO_GOSTRING_TYPEDEF
- typedef _GoString_ GoString;
- #endif
- typedef void *GoMap;
- typedef void *GoChan;
- typedef struct { void *t; void *v; } GoInterface;
- typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
-
- #endif
-
- /* End of boilerplate cgo prologue. */
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
-
- extern GoInt DCall();
-
- extern char* DCallWithParam(char* p0);
-
- #ifdef __cplusplus
- }
- #endif
Golang代码调用
pluginLoad.go
- package main
-
- import "C"
- import (
- "fmt"
- "syscall"
- "unsafe"
- )
-
- func main() {
- dll := syscall.NewLazyDLL("plugin.dll")
- f := dll.NewProc("DCall")
- res, _, _ := f.Call()
- fmt.Println(res)
-
- f2 := dll.NewProc("DCallWithParam")
- r, _, _ := f2.Call(uintptr(unsafe.Pointer(syscall.StringBytePtr("php2.cc"))))
- // 获取C返回的指针。
- // 注意C返回的r为char*,对应的Go类型为*byte
- p := (*byte)(unsafe.Pointer(r))
- // 定义一个[]byte切片,用来存储C返回的字符串
- data := make([]byte, 0)
- // 遍历C返回的char指针,直到 '\0' 为止
- for *p != 0 {
- data = append(data, *p) // 将得到的byte追加到末尾
- r += unsafe.Sizeof(byte(0)) // 移动指针,指向下一个char
- p = (*byte)(unsafe.Pointer(r)) // 获取指针的值,此时指针已经指向下一个char
- }
- name := string(data) // 将data转换为字符串
-
- fmt.Printf("Hello, %s!\n", name)
- }
域名命令:
- go run pluginLoad.go