标签:
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
在 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 的具体实现类实例来使用
具体接口与类实现代码如下:
实例化与调用:
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 定义示例
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 避免未知异常。
程序崩溃甚至异常提示都没有,可在加载 DLL 之前: