【C# 调用 Go 语言】0x2 参数、返回值与类型转换

栏目: IT技术 · 发布时间: 4年前

内容简介:在上篇文章本文源代码可以在  https://gitee.com/coderbusy/golang-with-csharp 找到。使用 Golang 编写一个名为 Check 的方法,该方法接收两个整型的参数(i1,i2)并返回一个布尔值,当 i1 > i2 时返回值为 True,否则为 False :

在上篇文章 【C# 调用 Go 语言】0x1 Hello Golang 中,我们将 Golang 源码编译为动态链接库(dll),用 C# 调用 Golang 导出的方法并成功的看到了控制台的输出。本篇文章将对 C# 调用 Golang 方法做更详细的介绍,涉及如何对 Golang 方法进行传参、获取返回值以及处理调用过程中的类型转换。

本文源代码可以在  https://gitee.com/coderbusy/golang-with-csharp 找到。

基本的传参与返回值

使用 Golang 编写一个名为 Check 的方法,该方法接收两个整型的参数(i1,i2)并返回一个布尔值,当 i1 > i2 时返回值为 True,否则为 False :

【C# 调用 Go 语言】0x2 参数、返回值与类型转换

需要一个 make.bat 文件,用于生成动态链接库:

【C# 调用 Go 语言】0x2 参数、返回值与类型转换

同上篇,将 C# 项目 Golang.Ioc 的目标平台设置为 x86 ,将生成的 Golang.Ioc.Interop.dll 复制到项目中并设置为始终复制:

【C# 调用 Go 语言】0x2 参数、返回值与类型转换

使用 P/Invoke 调用导出的方法:

【C# 调用 Go 语言】0x2 参数、返回值与类型转换

运行之后,程序将会产生如下输出,程序行为符合我们的预期:

【C# 调用 Go 语言】0x2 参数、返回值与类型转换

C、CGO、Golang 与 P/Invoke

C/C++ 经过几十年的发展,已经积累了庞大的软件资产,它们很多久经考验而且性能已经足够优化。Go 语言必须能够站在 C/C++ 这个巨人的肩膀之上,有了海量的 C/C++ 软件资产兜底之后,我们才可以放心愉快地用 Go 语言编程。C 语言作为一个通用语言,很多库会选择提供一个 C 兼容的 API,然后用其他不同的编程语言实现。Go 语言通过自带的一个叫 CGO 的 工具 来支持 C 语言函数调用,同时我们可以用 Go 语言导出 C 动态库接口给其它语言使用。

Go语言高级编程 》 第二章 CGO编程

P/Invoke 的全称是 Platform Invoke (平台调用) 它实际上是一种函数调用机制,通过 P/Invoke 我们就可以调用非托管 DLL 中的函数。实际上很多 NET 基类库中定义的类型内部调用了从 Kernel32.dll,User32.dll,gdi32.dll 等非托管 DLL 中导出的函数。

之所以可以在 C# 中调用 Golang 程序集是因为 CGO 在中间充当了桥梁。我们的调用顺序应该是 C# -> C -> Golang 。

下表列出了 Windows API 和 C 样式函数中使用的数据类型。许多非托管库包含将这些数据类型作为参数和返回值传递的函数。第三列列出了相应的 .NET Framework 内置值类型或可在托管代码中使用的类。

Windows API 中的非托管类型 非托管 C 语言类型 托管类型 描述
VOID void System.Void 应用于不返回值的函数。
HANDLE void * System.IntPtr 或 System.UIntPtr 在 32 位 Windows 操作系统上为 32 位、在 64 位 Windows 操作系统上为 64 位。
BYTE unsigned char System.Byte 8 位
SHORT short System.Int16 16 位
WORD unsigned short System.UInt16 16 位
INT int System.Int32 32 位
UINT unsigned int System.UInt32 32 位
LONG long System.Int32 32 位
BOOL long System.Boolean 或 System.Int32 32 位
DWORD unsigned long System.UInt32 32 位
ULONG unsigned long System.UInt32 32 位
CHAR char System.Char 使用 ANSI 修饰。
WCHAR wchar_t System.Char 使用 Unicode 修饰。
LPSTR char * System.String 或 System.Text.StringBuilder 使用 ANSI 修饰。
LPCSTR const char * System.String 或 System.Text.StringBuilder 使用 ANSI 修饰。
LPWSTR wchar_t * System.String 或 System.Text.StringBuilder 使用 Unicode 修饰。
LPCWSTR const wchar_t * System.String 或 System.Text.StringBuilder 使用 Unicode 修饰。
FLOAT float System.Single 32 位
DOUBLE double System.Double 64 位

Go语言中数值类型和 C语言 数据类型基本上是相似的,以下是它们的对应关系表:

C语言类型 CGO类型 Go语言类型
char C.char byte
singed char C.schar int8
unsigned char C.uchar uint8
short C.short int16
unsigned short C.short uint16
int C.int int32
unsigned int C.uint uint32
long C.long int32
unsigned long C.ulong uint32
long long int C.longlong int64
unsigned long long int C.ulonglong uint64
float C.float float32
double C.double float64
size_t C.size_t uint

需要注意的是,虽然在C语言中int、short等类型没有明确定义内存大小,但是在CGO中它们的内存大小是确定的。在CGO中,C语言的int和long类型都是对应4个字节的内存大小,size_t类型可以当作Go语言uint无符号整数类型对待。

在编写完 Golang 代码后,如果不确定对应的 C# 类型,那么可以查看在编译后与 DLL 同时生成的 .h 头文件,对应上面两张表应该就可以找到正确的类型 。

字符串类型参数

如果一个方法需要导出并且参数或返回值涉及到字符串,通常使用 *C.char 来代替 Golang 内置的 string 类型对外导出。可以调用 C.CString 方法将 Golang 的字符串类型转为 *C.char 类型:

【C# 调用 Go 语言】0x2 参数、返回值与类型转换

需要注意的是:C string 在 C 的堆上使用 malloc 申请。调用者有责任在合适的时候对该字符串进行释放,释放方式可以是调用C.free(调用C.free需包含stdlib.h)。

在 Golang 源码中新增 GetSlogan 方法,该方法接受一个名为 name 的字符串参数,并返回一句为武汉加油的口号。为了可以在返回值使用完成后释放掉由 C.CString 申请的内存,再增加一个 Free 方法:

【C# 调用 Go 语言】0x2 参数、返回值与类型转换

C# 提供一个 ICustomMarshaler 接口,可以用它来对托管内存和非托管内存进行转换。添加一个 CStringMarshaler  实现 ICustomMarshaler 接口,帮我们处理 C# string 和 C.CString 之间的转换过程,并保证内存被正确释放:

【C# 调用 Go 语言】0x2 参数、返回值与类型转换

测试一下对 GetSlogan 方法的调用:

【C# 调用 Go 语言】0x2 参数、返回值与类型转换

运行代码后将产生以下输出:

【C# 调用 Go 语言】0x2 参数、返回值与类型转换

增加代码进行性能测试:

【C# 调用 Go 语言】0x2 参数、返回值与类型转换

调用 52 万 1 千次后,内存占用仍在 20M 以内,可以证明没有发生内存泄漏问题:

【C# 调用 Go 语言】0x2 参数、返回值与类型转换

以上所述就是小编给大家介绍的《【C# 调用 Go 语言】0x2 参数、返回值与类型转换》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

React

React

卓越开发者联盟 / 寸志、范洪春、杨森、陈涌 / 电子工业出版社 / 2015-5-1 / CNY 65.00

2014 年横空出世的由Facebook 推出的开源框架React.js,基于Virtual DOM 重新定义了用户界面的开发方式,彻底革新了大家对前端框架的认识,将PHP 风格的开发方式迁移到客户端应用开发。其优势在于可以与各种类库、框架搭配使用。《React:引领未来的用户界面开发框架》是这一领域的首作,由多位一线专家精心撰写,采用一个全程实例全面介绍和剖析了ReactReact.js 的方方......一起来看看 《React》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具