C# 结合 Golang 开发
2021-05-18 20:29
标签:pack toolchain tin 程序 sys 程序崩溃 不同的 ++ ide 基本方式:将 Go 程序编译成 DLL 供 C# 调用。 注意:代码中 export 的注释是定义的入口描述不能省略 在 LiteIDE 中将编译配置的 生成 DLL 依赖于 gcc,没有 gcc 环境时,会报以下错误: "gcc": executable file not found in %PATH% GCC下载:Windows 64位版本? || Windows 32位版本,也可以从从云盘下载。 在 LiteIDE 中,可以通过配置 在 c# 中判断操作系统是否 64 位,可以使用以下语句。 为了在不同的操作系统下,加载不同的 DLL,采取以下步骤来进行组织。 实例化与调用: C# GoString struct 定义 C# DllImport 声明 C# GoString struct 转 String C# 调用示例 CallingConvention 程序崩溃甚至异常提示都没有,可在加载 DLL 之前: C# 结合 Golang 开发 标签:pack toolchain tin 程序 sys 程序崩溃 不同的 ++ ide 原文地址:https://www.cnblogs.com/timeddd/p/11731160.html1. 实现方式与语法形式
1.1 Go代码
package main
import "C"
import "fmt"
func main() {
fmt.Println(Test())
}
var _count = 0
//Test :
//export Test
func Test() int {
_count++
return _count
}
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 下编译依赖的环境
下载之后,解压后确保 gcc 命令在搜索路径(Path)中。
更多信息可参考:https://www.cnblogs.com/ghj1976/p/3540257.html3. 操作系统 64 位与 32 的编译
win32.env
和 win64.env
来指定不同的 gcc 环境路径达到生成指定系统的 DLL 文件。4. c# 中操作系统 64 位与 32 的适配
bool is64 = Environment.Is64BitOperatingSystem;
(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 字符串转换
GO 定义示例//Hello :
//export Hello
func Hello(name *C.char) string {
return fmt.Sprintf("hello %s", C.GoString(name))
}
public struct GoString
{
public IntPtr p;
public int n;
public GoString(IntPtr n1, int n2)
{
p = n1; n = n2;
}
}
[DllImport(DLL_NAME, EntryPoint = "Hello", CallingConvention = CallingConvention.Cdecl)]
public extern static GoString Hello(byte[] name);
public string GoStringToCSharpString(GoString goString)
{
byte[] bytes = new byte[goString.n];
for (int i = 0; i
GoString goResult = test.Hello(Encoding.UTF8.GetBytes("张三"));
Debug.WriteLine(GoStringToCSharpString(goResult));
5.2 调试
在声明中加入 CallingConvention = CallingConvention.Cdecl
避免未知异常。[DllImport("Test.dll", CallingConvention = CallingConvention.Cdecl)]
Environment.SetEnvironmentVariable("GODEBUG", "cgocheck=0");
6. 相关参考
https://github.com/Baozisoftware/go-dll
https://stackoverflow.com/questions/48208098/using-generated-golang-dll-to-return-string-or-c-char