C# 结合 Golang 开发
基本方式:将 Go 程序编译成 DLL 供 C# 调用。
1.1 Go代码
注意:代码中 export 的注释是定义的入口描述不能省略
<pre class="has"><code>package main import "C" import "fmt" func main() { fmt.Println(Test()) } var _count = 0 //Test : //export Test func Test() int { _count return _count } </code></pre>在 LiteIDE 中将编译配置的 <code>BUILDARGS</code> 自定义值为 <code>--buildmode=c-shared -o Test.dll</code>,从而形成以下编译语句。
<pre class="has"><code>go build --buildmode=c-shared -o Test.dll </code></pre>1.2 C# 代码
<pre class="has"><code>[DllImport("Test.dll", EntryPoint = "Test")] extern static int Test(); </code></pre> <h3>2. Windows 下编译依赖的环境</h3>生成 DLL 依赖于 gcc,没有 gcc 环境时,会报以下错误:
<blockquote>"gcc": executable file not found in %PATH%
</blockquote>GCC下载:Windows 64位版本 || Windows 32位版本,也可以从从云盘下载。
下载之后,解压后确保 gcc 命令在搜索路径(Path)中。
更多信息可参考:https://www.cnblogs.com/ghj1976/p/3540257.html
在 LiteIDE 中,可以通过配置 <code>win32.env</code> 和 <code>win64.env</code> 来指定不同的 gcc 环境路径达到生成指定系统的 DLL 文件。
<h3>4. c# 中操作系统 64 位与 32 的适配</h3>在 c# 中判断操作系统是否 64 位,可以使用以下语句。
<pre class="has"><code>bool is64 = Environment.Is64BitOperatingSystem; </code></pre>为了在不同的操作系统下,加载不同的 DLL,采取以下步骤来进行组织。
(1)将 32 位的版本命名为 Test32.dll,将 64 位的版本命名为 Test64.dll
(2)定义 ITest 接口,将 DLL 将要调用的方法定义为接口方法
(3)分别为ITest接口实现 Test32 与 Test64 类,在类中加载相应的 DLL
(4)通过判断操作系统类型,实例化一个 ITest 的具体实现类实例来使用
具体接口与类实现代码如下:
实例化与调用:
<pre class="has"><code>ITest test = Environment.Is64BitOperatingSystem ? (ITest)new Test64() : (ITest)new Test32(); int result = test.Test(); </code></pre> <h3>5. 其它一些问题</h3>5.1 字符串转换
<ul><li>传入字符串,C#: byte[] -> GO: *C.char</li><li>接收字符串,GO: string -> C#: GoString structGO 定义示例</li></ul><pre class="has"><code>//Hello : //export Hello func Hello(name *C.char) string { return fmt.Sprintf("hello %s", C.GoString(name)) } </code></pre>
C# GoString struct 定义
<pre class="has"><code>public struct GoString { public IntPtr p; public int n; public GoString(IntPtr n1, int n2) { p = n1; n = n2; } } </code></pre>C# DllImport 声明
<pre class="has"><code>[DllImport(DLL_NAME, EntryPoint = "Hello", CallingConvention = CallingConvention.Cdecl)] public extern static GoString Hello(byte[] name); </code></pre>C# GoString struct 转 String
<pre class="has"><code>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; } </code></pre>C# 调用示例
<pre class="has"><code>GoString goResult = test.Hello(Encoding.UTF8.GetBytes("张三")); Debug.WriteLine(GoStringToCSharpString(goResult)); </code></pre>5.2 调试
CallingConvention
在声明中加入 <code>CallingConvention = CallingConvention.Cdecl</code> 避免未知异常。
程序崩溃甚至异常提示都没有,可在加载 DLL 之前:
<pre class="has"><code>Environment.SetEnvironmentVariable("GODEBUG", "cgocheck=0"); </code></pre> <h3>6. 相关参考</h3> <ul><li>GO 生成 DLL,C# 调用的一个完整小示例:https://github.com/Baozisoftware/go-dll</li><li>字符串处理相关的一个问答
https://stackoverflow.com/questions/48208098/using-generated-golang-dll-to-return-string-or-c-char</li></ul> 到此这篇关于“C# 结合 Golang 开发”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!
您可能感兴趣的文章:
学习golang开始前的准备工作
PHP7 Swoole/Nginx/Golang 数字货币交易所通信方式
2018年最全Go语言教程零基础入门到进阶实战视频
Golang开发语言的效率
使用Go语言一段时间的感受
关于Golang的介绍
为什么要学 Go
Golang 编辑器
为什么要学go语言,golang的优势有哪些?
php和go哪个适合新人