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# 调用的一个完整小示例:
https://github.com/Baozisoftware/go-dll - 字符串处理相关的一个问答
https://stackoverflow.com/questions/48208098/using-generated-golang-dll-to-return-string-or-c-char
C# 结合 Golang 开发的更多相关文章
- 使用golang 开发的 andriod应用
最近在捣鼓一个东东,就是使用golang开发andriod应用.说起来简单操作起来还挺麻烦,中间又学习了很多东西.比如ubuntu,docker,angular,ionic,jquery mobile ...
- golang开发android环境搭建_window
golang开发android环境搭建介绍 一 安装依赖软件: git:版本管理 go: go开发环境(版本>=1.5),可直接下载window版的go安装包. android studio: ...
- Windows下visual studio code搭建golang开发环境
Windows下visual studio code搭建golang开发环境 序幕 其实环境搭建没什么难的,但是遇到一些问题,主要是有些网站资源访问不了(如:golang.org),导致一些包无法安装 ...
- linux golang开发环境配置(离线方式)
<获取开发工具> 到https://www.golangtc.com/download 下载安装包, 根据自己的系统选择合适的开发包,这里选择go.1.9.2.linux-amd6 ...
- miniblink+golang开发windows gui应用
golang的优点自不必说了,这么好的语言怎么能缺少界面库呢?所以我使用miniblink开发了一个可以用html,css,js开发界面的浏览器,通过它你能为你的golang开发简单的界面.说白了其实 ...
- Linux下golang开发环境搭建
对于golang开发来说,Windows下可以用vscode或者liteide都不错,但是Linux下的开发也就只有vim了,所以怎么搞笑的利用vim进行golang开发呢? 参考官方推荐的一个插件: ...
- window / Linux 下 Golang 开发环境的配置
一直专注于使用python语言进行程序开发,但是却又一直被它的性能问题所困扰,直到遇到了天生支持高并发的Golang,这似乎也成了学习go语言最理所当然的理由.下面介绍下Go语言开发环境搭建的步骤: ...
- Golang开发环境搭建-Vim篇
一.一个干净的环境 找个干净的基础环境,方便确认每个搭建步骤后的效果: Ubuntu 14.04 x86_64 vim version 7.4.52 go version go1.4beta1 lin ...
- Golang开发支持平滑升级(优雅重启)的HTTP服务
Golang开发支持平滑升级(优雅重启)的HTTP服务 - tabalt的博客 http://tabalt.net/blog/graceful-http-server-for-golang/ http ...
- Visual Studio Code配置GoLang开发环境
Visual Studio Code配置GoLang开发环境 在Visual Studio Code配置GoLang开发环境 作者:chszs,未经博主允许不得转载.经许可的转载需注明作者和博客主页: ...
随机推荐
- Elastic-Job:动态添加任务,支持动态分片
多情只有春庭月,犹为离人照落花. 概述 因项目中使用到定时任务,且服务部署多实例,因此需要解决定时任务重复执行的问题.即在同一时间点,每一个定时任务只在一个节点上执行.常见的开源方案,如 elasti ...
- 多线程编程学习十一(ThreadPoolExecutor 详解).
一.ThreadPoolExecutor 参数说明 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keep ...
- MOOC 数据库系统笔记(二):数据库系统的基本结构及其演变发展
数据库系统的结构抽象与演变 数据库的标准结构 DBMS管理数据的三个层次 1.External Level = User Level 某一用户能够看到与处理的数据,全局数据中的某一部分 2.Conce ...
- PTA A1009&A1010
第五天 A1009 Product of Polynomials (25 分) 题目内容 This time, you are supposed to find A×B where A and B a ...
- Vue学习之vue中的计算属性和侦听器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- git使用笔记-git项目的建立及配置、创建子分支及独立分支、分支重命名
一.git的基本使用 1.下载安装git (略) 2.配置gitconfig 配置内容:(主要是你的git的账户信息,提交命令的别名) 3.配置git公钥(输入$ ssh-keygen -t rsa ...
- Spring Cloud 初认识
Spring Cloud是一个继承了众多开源的框架,其利用了Springboot开发的便利性来实现分布式服务功能,是一套开放.易部署.易维护的分布式开发工具包,而且有成熟的社区且社区活跃度很高.Spr ...
- angular 配置开发环境、测试环境、生产环境
1. 配置开发环境.测试环境.生产环境 (1). environment.ts - 开发环境: 用于程序开发 (创建项目时自动生成) export const environment = { prod ...
- Mybatis基础知识点
1. Mybatis框架优缺点 优点: 1. 易于上手和掌握. 2. sql写在xml里,便于统一管理和优化. 3. 解除sql与程序代码的耦合. 4. 提供映射标签,支持对象与数据库的orm字段关系 ...
- Scala 学习笔记之集合(1)
package com.citi.scala object CollectionDemo { def main(args: Array[String]): Unit = { /** * List */ ...