在Windows环境下,我们可以将Go语言编译为DLL并供.Net等其他语言的代码调用,需要用到Mingw64的gcc编译器(请注意,不是MinGW)。

一、环境信息
1、Go
Go语言版本需要大于1.10,否则会报错:

1
-buildmode=shared not supported on windows/amd64

具体可参见:https://golang.org/doc/go1.10#compiler

2、Mingw64
Mingw64是gcc官方唯一支持的环境,可从http://www.mingw-w64.org/doku.php/download下载,安装时的架构选择x86_64即可,在安装完成后将Mingw64的bin目录(如D:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin)加入到PATH环境变量中,然后可以查看Go、Mingw64、gcc的版本:

查看Go、Mingw64及gcc版本

查看Go、Mingw64及gcc版本

请注意,Mingw64的平台应和GOARCH的平台一致。例如,笔者的64位Win10下编译出的DLL文件为x64架构的:

注意Mingw架构

注意Mingw架构

二、编写代码
在代码中导出要导出的函数,以下的代码被抄得到处都是:

main.go
Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main
import "C"
import "fmt"
//export PrintBye
func PrintBye() {
    fmt.Println("From DLL: Bye!")
}
//export Sum
func Sum(a int, b int) int {
    return a + b;
}
func main() {
    // Need a main function to make CGO compile package as C shared library
}

其中://export的注释是必须的;main函数也是必须的,即使main函数是空的;如有必要,依然可以加入init函数。

三、编译为DLL
使用命令:

1
go build -buildmode=c-shared -o exportgo.dll main.go

即可直接将main.go编译为exportgo.dll。
我们可以使用《在Java中进行中文繁体简体转换,基于OpenCC(Open Chinese Convert)方案》中描述的dumpbin工具或Dependency Walker查看导出的DLL是否正确:

使用dumpbin查看DLL文件

使用dumpbin查看DLL文件

我们会发现除了PrintBye和Sum函数外,Go语言中自带的大量package中的函数也被导出了,多达17000余个。
此外,还可以通过 -ldflags 指定链接器参数去除符号表及调试信息等。
此外,如果要编译为静态库,可以使用:

1
go build -buildmode=c-archive main.go

执行完毕后会在当前目录生成main.a和main.h文件。
四、交叉编译
我们可以使用命令:

1
go tool dist list

查看当前支持的交叉编译环境(GOOS/GOARCH):

查看Go支持的交叉编译环境

查看Go支持的交叉编译环境

然后使用命令:

1
2
3
4
set GOOS=linux
set GOARCH=386
set CGO_ENABLED=0
go build

配合对应的交叉编译链即可实现交叉编译。

五、.Net调用Go编译出的DLL
根据导出函数定义进行声明:

C#
1
2
3
4
5
[DllImport("exportgo.dll", EntryPoint = "PrintBye")]
static extern void PrintBye();
 
[DllImport("exportgo.dll", EntryPoint = "Sum")]
static extern int Sum(int a, int b);

然后调用:

1
2
3
4
5
6
7
private void button_SaveSetting_Click(object sender, EventArgs e)
{
    Console.WriteLine("Call go dll test");
 
    PrintBye();
    Console.WriteLine(Sum(33, 22));
}

将DLL文件与.Net编译出的可执行文件放在一起执行,并观察stdout的输出:

.Net调用Go语言DLL测试

.Net调用Go语言DLL测试

参考资料:
1、https://stackoverflow.com/questions/40573401/building-a-dll-with-go-1-7
2、https://my.oschina.net/bfbd/blog/1622767
3、https://blog.csdn.net/rtduq/article/details/80340461
4、https://blog.csdn.net/xulingyun20032003/article/details/81220098

转载时请保留出处,违法转载追究到底:进城务工人员小梅 » Windows环境下将Go语言编译为DLL并供.Net调用