C# 结合 Golang 开发
1. 實(shí)現(xiàn)方式與語(yǔ)法形式
基本方式:將 Go 程序編譯成 DLL 供 C# 調(diào)用。
1.1 Go代碼
注意:代碼中 export 的注釋是定義的入口描述不能省略
package mainimport "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,從而形成以下編譯語(yǔ)句。
go build --buildmode=c-shared -o Test.dll1.2 C# 代碼
[DllImport("Test.dll", EntryPoint = "Test")]extern static int Test();
2. Windows 下編譯依賴(lài)的環(huán)境
生成 DLL 依賴(lài)于 gcc,沒(méi)有 gcc 環(huán)境時(shí),會(huì)報(bào)以下錯(cuò)誤:
"gcc": executable file not found in %PATH%
GCC下載:Windows 64位版本? || Windows 32位版本,也可以從從云盤(pán)下載。
下載之后,解壓后確保 gcc 命令在搜索路徑(Path)中。
更多信息可參考:https://www.cnblogs.com/ghj1976/p/3540257.html
3. 操作系統(tǒng) 64 位與 32 的編譯
在 LiteIDE 中,可以通過(guò)配置?win32.env?和?win64.env?來(lái)指定不同的 gcc 環(huán)境路徑達(dá)到生成指定系統(tǒng)的 DLL 文件。
4. c# 中操作系統(tǒng) 64 位與 32 的適配
在 c# 中判斷操作系統(tǒng)是否 64 位,可以使用以下語(yǔ)句。
bool is64 = Environment.Is64BitOperatingSystem;為了在不同的操作系統(tǒng)下,加載不同的 DLL,采取以下步驟來(lái)進(jìn)行組織。
(1)將 32 位的版本命名為 Test32.dll,將 64 位的版本命名為 Test64.dll
(2)定義 ITest 接口,將 DLL 將要調(diào)用的方法定義為接口方法
(3)分別為ITest接口實(shí)現(xiàn) Test32 與 Test64 類(lèi),在類(lèi)中加載相應(yīng)的 DLL
(4)通過(guò)判斷操作系統(tǒng)類(lèi)型,實(shí)例化一個(gè) ITest 的具體實(shí)現(xiàn)類(lèi)實(shí)例來(lái)使用
具體接口與類(lèi)實(shí)現(xiàn)代碼如下:
{
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();
}
}
實(shí)例化與調(diào)用:
ITest test = Environment.Is64BitOperatingSystem ? (ITest)new Test64() : (ITest)new Test32();int result = test.Test();
5. 其它一些問(wèn)題
5.1 字符串轉(zhuǎn)換
傳入字符串,C#: byte[] -> GO: *C.char
接收字符串,GO: string -> C#: GoString struct
GO 定義示例
//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 轉(zhuǎn) 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# 調(diào)用示例
GoString goResult = test.Hello(Encoding.UTF8.GetBytes("張三"));Debug.WriteLine(GoStringToCSharpString(goResult));
5.2 調(diào)試
CallingConvention
在聲明中加入?CallingConvention = CallingConvention.Cdecl?避免未知異常。
程序崩潰甚至異常提示都沒(méi)有,可在加載 DLL 之前:
Environment.SetEnvironmentVariable("GODEBUG", "cgocheck=0");6. 相關(guān)參考
GO 生成 DLL,C# 調(diào)用的一個(gè)完整小示例:
https://github.com/Baozisoftware/go-dll字符串處理相關(guān)的一個(gè)問(wèn)答
https://stackoverflow.com/questions/48208098/using-generated-golang-dll-to-return-string-or-c-char
總結(jié)
以上是生活随笔為你收集整理的C# 结合 Golang 开发的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 超过1w的Github Star大佬和他
- 下一篇: 未雨绸缪 | 一文简介 Azure Fr