日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > C# >内容正文

C#

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

發(fā)布時(shí)間:2023/12/4 C# 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C# 调用 Go 语言】0x2 参数、返回值与类型转换 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在上篇文章【C# 調(diào)用 Go 語(yǔ)言】0x1 Hello Golang ?中,我們將 Golang 源碼編譯為動(dòng)態(tài)鏈接庫(kù)(dll),用 C# 調(diào)用 Golang 導(dǎo)出的方法并成功的看到了控制臺(tái)的輸出。本篇文章將對(duì) C# 調(diào)用 Golang 方法做更詳細(xì)的介紹,涉及如何對(duì) Golang 方法進(jìn)行傳參、獲取返回值以及處理調(diào)用過(guò)程中的類(lèi)型轉(zhuǎn)換。

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

基本的傳參與返回值

使用 Golang 編寫(xiě)一個(gè)名為 Check 的方法,該方法接收兩個(gè)整型的參數(shù)(i1,i2)并返回一個(gè)布爾值,當(dāng) i1 > i2 時(shí)返回值為 True,否則為 False :

需要一個(gè) make.bat 文件,用于生成動(dòng)態(tài)鏈接庫(kù):

同上篇,將 C# 項(xiàng)目 Golang.Ioc 的目標(biāo)平臺(tái)設(shè)置為 x86 ,將生成的 Golang.Ioc.Interop.dll 復(fù)制到項(xiàng)目中并設(shè)置為始終復(fù)制:

使用 P/Invoke 調(diào)用導(dǎo)出的方法:

運(yùn)行之后,程序?qū)?huì)產(chǎn)生如下輸出,程序行為符合我們的預(yù)期:

C、CGO、Golang 與 P/Invoke

C/C++ 經(jīng)過(guò)幾十年的發(fā)展,已經(jīng)積累了龐大的軟件資產(chǎn),它們很多久經(jīng)考驗(yàn)而且性能已經(jīng)足夠優(yōu)化。Go 語(yǔ)言必須能夠站在 C/C++ 這個(gè)巨人的肩膀之上,有了海量的 C/C++ 軟件資產(chǎn)兜底之后,我們才可以放心愉快地用 Go 語(yǔ)言編程。C 語(yǔ)言作為一個(gè)通用語(yǔ)言,很多庫(kù)會(huì)選擇提供一個(gè) C 兼容的 API,然后用其他不同的編程語(yǔ)言實(shí)現(xiàn)。Go 語(yǔ)言通過(guò)自帶的一個(gè)叫 CGO 的工具來(lái)支持 C 語(yǔ)言函數(shù)調(diào)用,同時(shí)我們可以用 Go 語(yǔ)言導(dǎo)出 C 動(dòng)態(tài)庫(kù)接口給其它語(yǔ)言使用。

Go語(yǔ)言高級(jí)編程?》?第二章 CGO編程

P/Invoke 的全稱(chēng)是 Platform Invoke (平臺(tái)調(diào)用) 它實(shí)際上是一種函數(shù)調(diào)用機(jī)制,通過(guò) P/Invoke 我們就可以調(diào)用非托管 DLL 中的函數(shù)。實(shí)際上很多 NET 基類(lèi)庫(kù)中定義的類(lèi)型內(nèi)部調(diào)用了從 Kernel32.dll,User32.dll,gdi32.dll 等非托管 DLL 中導(dǎo)出的函數(shù)。

之所以可以在 C# 中調(diào)用 Golang 程序集是因?yàn)?CGO 在中間充當(dāng)了橋梁。我們的調(diào)用順序應(yīng)該是 C# -> C -> Golang 。

下表列出了 Windows API 和 C 樣式函數(shù)中使用的數(shù)據(jù)類(lèi)型。許多非托管庫(kù)包含將這些數(shù)據(jù)類(lèi)型作為參數(shù)和返回值傳遞的函數(shù)。第三列列出了相應(yīng)的 .NET Framework 內(nèi)置值類(lèi)型或可在托管代碼中使用的類(lèi)。

Windows API 中的非托管類(lèi)型非托管 C 語(yǔ)言類(lèi)型托管類(lèi)型描述
VOIDvoidSystem.Void應(yīng)用于不返回值的函數(shù)。
HANDLEvoid *System.IntPtr?或?System.UIntPtr在 32 位 Windows 操作系統(tǒng)上為 32 位、在 64 位 Windows 操作系統(tǒng)上為 64 位。
BYTEunsigned charSystem.Byte8 位
SHORTshortSystem.Int1616 位
WORDunsigned shortSystem.UInt1616 位
INTintSystem.Int3232 位
UINTunsigned intSystem.UInt3232 位
LONGlongSystem.Int3232 位
BOOLlongSystem.Boolean?或?System.Int3232 位
DWORDunsigned longSystem.UInt3232 位
ULONGunsigned longSystem.UInt3232 位
CHARcharSystem.Char使用 ANSI 修飾。
WCHARwchar_tSystem.Char使用 Unicode 修飾。
LPSTRchar *System.String?或?System.Text.StringBuilder使用 ANSI 修飾。
LPCSTRconst char *System.String?或?System.Text.StringBuilder使用 ANSI 修飾。
LPWSTRwchar_t *System.String?或?System.Text.StringBuilder使用 Unicode 修飾。
LPCWSTRconst wchar_t *System.String?或?System.Text.StringBuilder使用 Unicode 修飾。
FLOATfloatSystem.Single32 位
DOUBLEdoubleSystem.Double64 位

Go語(yǔ)言中數(shù)值類(lèi)型和C語(yǔ)言數(shù)據(jù)類(lèi)型基本上是相似的,以下是它們的對(duì)應(yīng)關(guān)系表:

C語(yǔ)言類(lèi)型CGO類(lèi)型Go語(yǔ)言類(lèi)型
charC.charbyte
singed charC.scharint8
unsigned charC.ucharuint8
shortC.shortint16
unsigned shortC.shortuint16
intC.intint32
unsigned intC.uintuint32
longC.longint32
unsigned longC.ulonguint32
long long intC.longlongint64
unsigned long long intC.ulonglonguint64
floatC.floatfloat32
doubleC.doublefloat64
size_tC.size_tuint

需要注意的是,雖然在C語(yǔ)言中int、short等類(lèi)型沒(méi)有明確定義內(nèi)存大小,但是在CGO中它們的內(nèi)存大小是確定的。在CGO中,C語(yǔ)言的int和long類(lèi)型都是對(duì)應(yīng)4個(gè)字節(jié)的內(nèi)存大小,size_t類(lèi)型可以當(dāng)作Go語(yǔ)言u(píng)int無(wú)符號(hào)整數(shù)類(lèi)型對(duì)待。

在編寫(xiě)完 Golang 代碼后,如果不確定對(duì)應(yīng)的 C# 類(lèi)型,那么可以查看在編譯后與 DLL 同時(shí)生成的 .h 頭文件,對(duì)應(yīng)上面兩張表應(yīng)該就可以找到正確的類(lèi)型 。

字符串類(lèi)型參數(shù)

如果一個(gè)方法需要導(dǎo)出并且參數(shù)或返回值涉及到字符串,通常使用 *C.char 來(lái)代替 Golang 內(nèi)置的 string 類(lèi)型對(duì)外導(dǎo)出。可以調(diào)用 C.CString 方法將 Golang 的字符串類(lèi)型轉(zhuǎn)為 *C.char 類(lèi)型:

需要注意的是:C string 在 C 的堆上使用 malloc 申請(qǐng)。調(diào)用者有責(zé)任在合適的時(shí)候?qū)υ撟址M(jìn)行釋放,釋放方式可以是調(diào)用C.free(調(diào)用C.free需包含stdlib.h)。

在 Golang 源碼中新增 GetSlogan 方法,該方法接受一個(gè)名為 name 的字符串參數(shù),并返回一句為武漢加油的口號(hào)。為了可以在返回值使用完成后釋放掉由 C.CString 申請(qǐng)的內(nèi)存,再增加一個(gè) Free 方法:

C# 提供一個(gè) ICustomMarshaler 接口,可以用它來(lái)對(duì)托管內(nèi)存和非托管內(nèi)存進(jìn)行轉(zhuǎn)換。添加一個(gè) CStringMarshaler ?實(shí)現(xiàn) ICustomMarshaler 接口,幫我們處理 C# string 和 C.CString 之間的轉(zhuǎn)換過(guò)程,并保證內(nèi)存被正確釋放:

測(cè)試一下對(duì) GetSlogan 方法的調(diào)用:

運(yùn)行代碼后將產(chǎn)生以下輸出:

增加代碼進(jìn)行性能測(cè)試:

調(diào)用 52 萬(wàn) 1 千次后,內(nèi)存占用仍在 20M 以?xún)?nèi),可以證明沒(méi)有發(fā)生內(nèi)存泄漏問(wèn)題:

總結(jié)

以上是生活随笔為你收集整理的【C# 调用 Go 语言】0x2 参数、返回值与类型转换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。