Go 程序编译成 DLL 供 C# 调用。

C# 结合 Golang 开发

 

1. 实现方式与语法形式

基本方式:将 Go 程序编译成 DLL 供 C# 调用。

1.1 Go代码

注意:代码中 export 的注释是定义的入口描述不能省略

package main

import "C"
import "fmt" func main() {
fmt.Println(Test())
} var _count = 0 //Test :
//export Test
func Test() int {
_count++
return _count
}

在 LiteIDE 中将编译配置的 BUILDARGS 自定义值为 --buildmode=c-shared -o Test.dll,从而形成以下编译语句。

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

1.2 C# 代码

[DllImport("Test.dll", EntryPoint = "Test")]
extern static int Test();

2. Windows 下编译依赖的环境

生成 DLL 依赖于 gcc,没有 gcc 环境时,会报以下错误:

"gcc": executable file not found in %PATH%

GCC下载:Windows 64位版本  || Windows 32位版本,也可以从从云盘下载
下载之后,解压后确保 gcc 命令在搜索路径(Path)中。
更多信息可参考:https://www.cnblogs.com/ghj1976/p/3540257.html

3. 操作系统 64 位与 32 的编译

在 LiteIDE 中,可以通过配置 win32.env 和 win64.env 来指定不同的 gcc 环境路径达到生成指定系统的 DLL 文件。

4. c# 中操作系统 64 位与 32 的适配

在 c# 中判断操作系统是否 64 位,可以使用以下语句。

bool is64 = Environment.Is64BitOperatingSystem;

为了在不同的操作系统下,加载不同的 DLL,采取以下步骤来进行组织。
(1)将 32 位的版本命名为 Test32.dll,将 64 位的版本命名为 Test64.dll
(2)定义 ITest 接口,将 DLL 将要调用的方法定义为接口方法
(3)分别为ITest接口实现 Test32 与 Test64 类,在类中加载相应的 DLL
(4)通过判断操作系统类型,实例化一个 ITest 的具体实现类实例来使用
具体接口与类实现代码如下:

public interface ITest
{
int Test();
} public class Test32 : ITest
{
class TestDLL
{
const string DLL_NAME = "Test32.dll"; [DllImport(DLL_NAME, EntryPoint = "Test")]
public extern static int Test();
} public int Test()
{
return TestDLL.Test();
}
} public class Test64 : ITest
{
class TestDLL
{
const string DLL_NAME = "Test64.dll"; [DllImport(DLL_NAME, EntryPoint = "Test")]
public extern static int Test();
} public int Test()
{
return TestDLL.Test();
}
}

实例化与调用:

ITest test = Environment.Is64BitOperatingSystem ? (ITest)new Test64() : (ITest)new Test32();
int result = test.Test();

5. 其它一些问题

5.1 字符串转换

  • 传入字符串,C#: byte[] -> GO: *C.char
  • 接收字符串,GO: string -> C#: GoString struct
    GO 定义示例
//Hello :
//export Hello
func Hello(name *C.char) string {
return fmt.Sprintf("hello %s", C.GoString(name))
}

C# GoString struct 定义

public struct GoString
{
public IntPtr p;
public int n;
public GoString(IntPtr n1, int n2)
{
p = n1; n = n2;
}
}

C# DllImport 声明

[DllImport(DLL_NAME, EntryPoint = "Hello", CallingConvention = CallingConvention.Cdecl)]
public extern static GoString Hello(byte[] name);

C# GoString struct 转 String

public string GoStringToCSharpString(GoString goString)
{
byte[] bytes = new byte[goString.n];
for (int i = 0; i < goString.n; i++)
{
bytes[i] = Marshal.ReadByte(goString.p, i);
}
string result = Encoding.UTF8.GetString(bytes);
return result;
}

C# 调用示例

GoString goResult = test.Hello(Encoding.UTF8.GetBytes("张三"));
Debug.WriteLine(GoStringToCSharpString(goResult));

5.2 调试

CallingConvention
在声明中加入 CallingConvention = CallingConvention.Cdecl 避免未知异常。

[DllImport("Test.dll", CallingConvention = CallingConvention.Cdecl)]

程序崩溃甚至异常提示都没有,可在加载 DLL 之前:

Environment.SetEnvironmentVariable("GODEBUG", "cgocheck=0");

6. 相关参考

Go 程序编译成 DLL 供 C# 调用。的更多相关文章

  1. Matlab函数编译成dll供c调用

    一 编译dll 在Command Window窗口中输入mbuild -setup,然后会出现语句,是否安装编译器,选择n,因为机子上已经安装了C/C++/C#的编译器,选择VS2010.

  2. 用IKVMC将jar转成dll供c#调用

    用IKVMC将jar转成dll供c#调用 ikvmc c# dll jar 用IKVMC将jar转成dll供c#调用 前言 ikvmc介绍 ikvmc下载安装 下载并解压 设置环境变量 jar-> ...

  3. (二)一个工作任务引起的乱战——C++程序编译为dll,让C#调用

    C++程序编译为C#可调用的dll的过程: 1.新建一个Win32 Console Application 项目,项目名为:DLLDemo,下一步选择Application type为DLL; 2.在 ...

  4. C#.NET常见问题(FAQ)-如何将cs文件编译成dll文件 exe文件 如何调用dll文件

    比如我要把TestDLL.cs文件编译成dll文件,则在命令提示符下,输入下面的命令,生成的文件为TestDLL.dll csc /target:library TestDLL.cs 注意前提是你安装 ...

  5. C#.NET如何将cs文件编译成dll文件 exe文件 如何调用dll文件

    比如我要把TestDLL.cs文件编译成dll文件,则在命令提示符下,输入下面的命令,生成的文件为TestDLL.dll csc /target:library TestDLL.cs 注意前提是你安装 ...

  6. Golang调用windows下的dll动态库中的函数 Golang 编译成 DLL 文件

    Golang调用windows下的dll动态库中的函数 package main import ( "fmt" "syscall" "time&quo ...

  7. asp.net源程序编译为dll文件并调用的实现过程

    很多时候,我们需要将.cs文件单独编译成.dll文件,这就需要使用csc命令将.cs文件编译成.dll动态链接库文件.具体的操作步骤如下: 打开命令窗口->输入cmd到控制台->cd C: ...

  8. Golang 编译成 DLL 文件

    golang 编译 dll 过程中需要用到 gcc,所以先安装 MinGW. windows 64 位系统应下载 MinGW 的 64 位版本: https://sourceforge.net/pro ...

  9. 关于.Net中Process的使用方法和各种用途汇总(二):用Process启动cmd.exe完成将cs编译成dll

    上一章博客我为大家介绍了Process类的所有基本使用方法,这一章博客我来为大家做一个小扩展,来熟悉一下Process类的实际使用,废话不多说我们开始演示. 先看看我们的软件要设计成的布局吧. 首先我 ...

随机推荐

  1. SQLserver无法删除数据库 "XXXX",因为该数据库当前正在使用。

    问题描述: 有时候删除库的时候,会显示无法删除数据库,因为该数据库当前正在使用. 解决方法: 方法一: EXEC msdb.dbo.sp_delete_database_backuphistory @ ...

  2. Java入门系列之字符串创建方式、判断相等(一)

    前言 陆续从0开始学习Java出于多掌握一门语言以后的路也会更宽,.NET和Java兼顾,虽然路还很艰难,但事在人为.由于Java和C#语法相似,所以关于一些很基础的内容不会再重头讲,Java系列中所 ...

  3. \" 转义字符, \a系统警报,逐字字符串(verbatim string)

    string str="The key factors are \"focus\" and \"perseverance\""; strin ...

  4. 5-网宿CDN客户端推流NGB

    网宿NGB调度系统(类似httpdns原理)从服务端分发给客户端推流IP,实现基于APP realip精准调度模式. 参考官网介绍:https://www.wangsu.com/content/det ...

  5. js绑定事件代理的坑

    js通过事件代理的方式绑定跳转事件,我这里的逻辑是把click事件绑定在最外层container上面,如果e.target包含我已经写好的class,则执行跳转逻辑.但是这种方式好像只能是在点击的元素 ...

  6. 用redis和cookie做单用户登录

    因为公司的项目需要用到单用户登录,于是今天用redis和cookie给系统添加了单用户登录功能,再次简单记录一下. 单用户登录是为了防止同一账户在不同电脑和不同浏览器里面同时登录.所以我这边的思路是: ...

  7. Vue.js+cube-ui(Scroll组件)实现类似头条效果的横向滚动导航条

    本博主在一次个人移动端项目中,遇到这么一个需求:希望自己的项目中,头部导航条的效果可以像今日头条那样,横向滚动! 对于这样的效果,在各大移动端项目中几乎是随处可见,为什么呢? 我们都知道,对于移动端也 ...

  8. python pyinstaller 模块的基本使用

    作用 PyInstaller是一个压缩python文件成为可执行程序的一个软件.它会扫描你所有的Python文档,并分析所有代码从而找出所有你的代码运行所需的模块.然后,PyInstaller会将所有 ...

  9. Maven报错Please ensure you are using JDK 1.4 or above and not a JRE

    在部署Jenkins项目时,用Jenkins调用服务器上脚本时,脚本在服务器上执行没有任何问题,但是在Jenkins上调用时就报错,提示mvn应该使用全路径执行,当加入jdk,jre,maven环境变 ...

  10. cluster集群基本概念

    cluster集群种类: 1,LB(Load Balance)负载均衡集群: 弱点:当横向扩展到一定机器后,发现在怎么横向加机器也没有效果的时候,瓶颈就卡在分发的服务器上了,也就是LB机器上了,如何解 ...