自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

聊聊 .NET9 FCall/QCall 調(diào)用約定

開(kāi)發(fā) 前端
.NET9里面需要在托管和非托管進(jìn)行相互調(diào)用,如果需要調(diào)用有效,就必須雙方互有約定。使托管代碼與CLR保持一致。比如FCall會(huì)通過(guò)一些宏定義打亂堆?;蛘呒拇嫫骼锩娴膮?shù)進(jìn)行重新排序,再比如FCall會(huì)對(duì)返回值,參數(shù),函數(shù)名稱(chēng)進(jìn)行重新構(gòu)造。

前言

FCall/Qcall是托管與非托管之間的調(diào)用約定,雙方需要一個(gè)契約,以彌合彼此的互相/單向調(diào)用。

非托管調(diào)用約定

先了解下非托管約定,一般有四種,分別為thiscall,stdcall ,cdecl ,fastcall 

thiscall:用特定的寄存器傳遞當(dāng)前類(lèi)指針this,由編譯器決定哪個(gè)寄存器傳遞this。自清理堆棧,從右往左傳遞參數(shù)。

stdcall:一般用于win32 API函數(shù)的傳遞方式,自身清理堆棧,從右往左一次傳參。

cdecl:一般用于微軟古老的MFC框架的類(lèi)的函數(shù)傳遞方式,調(diào)用者清理堆棧,從右往左依次傳參。

fastcall :用于快速調(diào)用方式,規(guī)定前幾個(gè)參數(shù)用寄存器傳遞,多余的參數(shù)用棧來(lái)傳遞。比如x64前四個(gè)參數(shù)rcx,rdx,r8,r9等。自身清理堆棧,從右往左傳參。

FCall

.NET9里面需要在托管和非托管進(jìn)行相互調(diào)用,如果需要調(diào)用有效,就必須雙方互有約定。使托管代碼與CLR保持一致。比如FCall會(huì)通過(guò)一些宏定義打亂堆棧或者寄存器里面的參數(shù)進(jìn)行重新排序,再比如FCall會(huì)對(duì)返回值,參數(shù),函數(shù)名稱(chēng)進(jìn)行重新構(gòu)造。FCall就是做這些的,下面看個(gè)例子----函數(shù)重構(gòu)。

例子:  

C# code: GC.CollectionCount(0);  
定義:
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern int _CollectionCount(int generation, int getSpecialGCCount);

非托管:

FCIMPL2(int, GCInterface::CollectionCount, INT32 generation, INT32 getSpecialGCCount)
{
    FCALL_CONTRACT;
    _ASSERTE(generation >= 0);
    int result = (INT32)GCHeapUtilities::GetGCHeap()->CollectionCount(generation, getSpecialGCCount);
    FC_GC_POLL_RET();
    return result;
}
FCIMPLEND

一般來(lái)說(shuō)FCall用FCIMPL宏定義開(kāi)頭,這么做的主要目的是:We align the native code shape to CoreCLR by implementing and using the and macros. These macro are responsible for using correct calling convention and shuffling the order of parameters on the stack. The macros also handle export of undecorated names using the alternatename linker/pragma trick. The downside of the trick is that linker doesn't see the comment pragma if there's no other reference to the .obj file inside a static library. There happened to be exactly two files that have only methods and no other referenced code. As a workaround I added a dummy reference from the .asm files for one function from each of those two files.FCIMPLxFCDECLxFCIMPLx。參考:https://github.com/dotnet/runtime/pull/99430

FCIMPL部分定義:

#define FCIMPL0(rettype, funcname) rettype funcname() { FCIMPL_PROLOG(funcname)
#define FCIMPL1(rettype, funcname, a1) rettype funcname(a1) {  FCIMPL_PROLOG(funcname)
#define FCIMPL1_V(rettype, funcname, a1) rettype funcname(a1) {  FCIMPL_PROLOG(funcname)
#define FCIMPL2(rettype, funcname, a1, a2) rettype funcname(a1, a2) {  FCIMPL_PROLOG(funcname)
#define FCIMPL2VA(rettype, funcname, a1, a2) rettype funcname(a1, a2, ...) {  FCIMPL_PROLOG(funcname)

下面代碼:

源碼:FCIMPL2(int, GCInterface::CollectionCount, INT32 generation, INT32 getSpecialGCCount)
宏定義:
#define FCIMPL2(rettype, funcname, a1, a2) rettype funcname(a1, a2) {  FCIMPL_PROLOG(funcname)
#define FCIMPLEND   FCIMPL_EPILOG(); }

展開(kāi)如下:

int GCInterface::CollectionCount(int generation,INT32 getSpecialGCCount)
{ 
   //FCIMPL2開(kāi)頭
   FCIMPL_PROLOG(funcname) 
   //函數(shù)主體部分
    FCALL_CONTRACT;
    _ASSERTE(generation >= 0);
    int result = (INT32)GCHeapUtilities::GetGCHeap()->CollectionCount(generation, getSpecialGCCount);
    FC_GC_POLL_RET();
    return result;
    //FCIMPL2結(jié)尾
    FCIMPL_EPILOG(); 
}

QCall

QCall一般使用導(dǎo)出標(biāo)記extern,用托管匹配 CLR調(diào)用,運(yùn)行出結(jié)果。調(diào)用約定遵循平臺(tái)標(biāo)準(zhǔn).

例子:把長(zhǎng)度為len個(gè)字節(jié)從str復(fù)制到desc

[DllImport("QCall", CharSet = CharSet.Unicode)]
private unsafe static extern void Buffer_MemMove(byte* dest, byte* src, [NativeInteger] UIntPtr len);

非托管Qcall

extern "C" void QCALLTYPE Buffer_MemMove(void *dst, void *src, size_t length)
{
    QCALL_CONTRACT;


    memmove(dst, src, length);
}

總結(jié)

簡(jiǎn)單點(diǎn)來(lái)說(shuō)FCall意思:調(diào)用托管函數(shù)的時(shí)候,可能會(huì)調(diào)用非托管,F(xiàn)Call就是從托管調(diào)用非托管的C#代碼與CLR之間的約定,約定它們?nèi)绾握{(diào)用。

QCall的意思:QCall一般用于非托管導(dǎo)出(extern)的函數(shù),在托管里面的調(diào)用。

責(zé)任編輯:武曉燕 來(lái)源: 江湖評(píng)談
相關(guān)推薦

2024-11-27 13:17:21

2024-02-22 16:58:56

.NET9LinuxConsole

2024-11-20 16:02:47

.NET 9LINQ開(kāi)發(fā)

2022-02-23 09:03:29

JavaScript開(kāi)發(fā)命名約定

2024-12-09 00:00:06

2009-08-19 15:24:30

.NET命名規(guī)范

2009-11-10 15:36:24

VB.NET命名約定

2025-02-06 13:57:26

2021-02-07 09:05:56

微服務(wù)結(jié)構(gòu)云原生

2021-07-11 12:12:49

.NETJWTjson

2025-01-03 08:29:53

2025-03-05 10:00:00

.NET 9C#開(kāi)發(fā)

2019-07-23 15:04:54

JavaScript調(diào)用棧事件循環(huán)

2025-03-03 00:48:12

微軟.NET 9Java

2018-06-20 15:33:44

Spring BootJava 9JDK

2021-07-14 06:45:49

Windows.NetTopshelf

2025-03-03 02:25:00

.NET 9JSON序列化

2021-06-08 09:28:12

.Net通知服務(wù)

2020-08-06 11:05:30

函數(shù)調(diào)用寄存器語(yǔ)言

2024-02-20 08:40:08

.NET 9智能應(yīng)用開(kāi)發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)