php调用go生成的dll,Windows环境下将Go语言编译为DLL并供.Net调用

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

一、环境信息

1、GoGo语言版本需要大于1.10,否则会报错:

-buildmode=shared not supported on windows/amd64

1

-buildmode=sharednotsupportedonwindows/amd64

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

2、Mingw64Mingw64是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的版本:

55c507ca4169b6e3ab0f5ef6e4dde8cf.png

查看Go、Mingw64及gcc版本

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

1a7371a726d92c0fdde969855a82a3bc.png

注意Mingw架构

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

main.go

Go

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

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

packagemain

import"C"

import"fmt"

//export PrintBye

funcPrintBye(){

fmt.Println("From DLL: Bye!")

}

//export Sum

funcSum(aint,bint)int{

returna+b;

}

funcmain(){

// Need a main function to make CGO compile package as C shared library

}

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

三、编译为DLL

使用命令:

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

1

gobuild-buildmode=c-shared-oexportgo.dllmain.go

即可直接将main.go编译为exportgo.dll。

我们可以使用《在Java中进行中文繁体简体转换,基于OpenCC(Open Chinese Convert)方案》中描述的dumpbin工具或Dependency Walker查看导出的DLL是否正确:

6ae1ebf5bdca04c9640b9b802c942e6e.png

使用dumpbin查看DLL文件

我们会发现除了PrintBye和Sum函数外,Go语言中自带的大量package中的函数也被导出了,多达17000余个。

此外,还可以通过

-ldflags 指定链接器参数去除符号表及调试信息等。

此外,如果要编译为静态库,可以使用:

go build -buildmode=c-archive main.go

1

gobuild-buildmode=c-archivemain.go

执行完毕后会在当前目录生成main.a和main.h文件。

四、交叉编译

我们可以使用命令:

go tool dist list

1

gotooldistlist

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

7089267fff525ae7dc2891dc76a0b3d0.png

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

然后使用命令:

set GOOS=linux

set GOARCH=386

set CGO_ENABLED=0

go build

1

2

3

4

setGOOS=linux

setGOARCH=386

setCGO_ENABLED=0

gobuild

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

五、.Net调用Go编译出的DLL

根据导出函数定义进行声明:

C#

[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

[DllImport("exportgo.dll",EntryPoint="PrintBye")]

staticexternvoidPrintBye();

[DllImport("exportgo.dll",EntryPoint="Sum")]

staticexternintSum(inta,intb);

然后调用:

private void button_SaveSetting_Click(object sender, EventArgs e)

{

Console.WriteLine("Call go dll test");

PrintBye();

Console.WriteLine(Sum(33, 22));

}

1

2

3

4

5

6

7

privatevoidbutton_SaveSetting_Click(objectsender,EventArgse)

{

Console.WriteLine("Call go dll test");

PrintBye();

Console.WriteLine(Sum(33,22));

}

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

6e3f797c697fe80a795911f5d4958efd.png

.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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值