Golang 编译生成 DLL 文件

去年的时候还在发愁如何用 Go 语言编译 DLL 文件, 今年就已经完全实现了,谷歌这样做是非常明智的。
编译过程中需要 gcc 的支持,Windows 环境下的 gcc 系统是 MinGW,去官网下载即可。地址是:
https://sourceforge.net/projects/mingw-w64/

编写 Go 语言程序:exportgo.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
}

注意:

  • 注释 //export PrintBye 和 //export Sum 在编译 DLL 的时候是必须的,说明了 DLL 需要输出的函数。注意注释和下面的函数名之间不能有空行。
  • 函数 main 也是必不可少的,但是不知道是否能够用它来做 DLL 的初始化,这个以后再仔细研究。

编译生成 DLL 文件

MinGW 安装后有一个叫做 Run terminal 的快捷方式,运行后进入命令行方式,进入 exportgo.go 所在目录,运行如下命令:

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

编译生成 exportgo.dll 和 exportgo.h 两个文件。

查看 DLL 的输出函数

有很多工具可以查看 DLL 的输出函数,我下载了 dllexp.exe 查看其内容,发现输出的内容很多,不知道是否有办法屏蔽掉没用的函数。当然,很容易找到我们的输出函数:
在这里插入图片描述

查看 exportgo.h 头文件

生成的 exportgo.h 文件也很重要,不仅可以让我们明白如何用 C 语言调用这个 DLL 库,也为用其他语言调用这个库提供了确切的参考指南。其中 Go 语言的内置数据类型在 C 语言中的等价声明,可以仔细看一下,对理解 Go 语言的数据结构很有帮助。

文件 exportgo.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 void PrintBye();
extern GoInt Sum(GoInt p0, GoInt p1);
#ifdef __cplusplus
}
#endif

用 C# 调用 DLL

using System;
using System.Runtime.InteropServices;

namespace HelloWorld
{
    class Hello 
    {
        [DllImport("exportgo.dll", EntryPoint="PrintBye")]
        static extern void PrintBye();

        [DllImport("exportgo.dll", EntryPoint="Sum")]
        static extern int Sum(int a, int b);

        static void Main() 
        {
            Console.WriteLine("Hello World!");
            PrintBye();
            Console.WriteLine(Sum(33, 22));
        }
    }
}
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

许野平

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值