Dela via


__clrcall

Anger att en funktion bara kan anropas från hanterad kod. Använd __clrcall för alla virtuella funktioner som bara anropas från hanterad kod. Den här anropskonventionen kan dock inte användas för funktioner som anropas från inbyggd kod. Den __clrcall modifieraren är Microsoft-specifik.

Använd __clrcall för att förbättra prestanda vid anrop från en hanterad funktion till en virtuell hanterad funktion eller från hanterad funktion till hanterad funktion via pekare.

Startpunkter är separata, kompilatorgenererade funktioner. Om en funktion har både interna och hanterade startpunkter är en av dem den faktiska funktionen med funktionsimplementeringen. Den andra funktionen är en separat funktion (en thunk) som anropar till den faktiska funktionen och låter den vanliga språkkörningen utföra PInvoke. När du markerar en funktion som __clrcall anger du att funktionsimplementeringen måste vara MSIL och att den inbyggda startpunktsfunktionen inte genereras.

När du tar adressen till en intern funktion om __clrcall inte har angetts använder kompilatorn den interna startpunkten. __clrcall anger att funktionen hanteras och att du inte behöver gå igenom övergången från hanterad till intern. I så fall använder kompilatorn den hanterade startpunkten.

När /clr (inte /clr:pure eller /clr:safe) används och __clrcall inte används returnerar adressen till en funktion alltid adressen till den interna startpunktsfunktionen. När __clrcall används skapas inte den interna startpunktsfunktionen, så du får adressen till den hanterade funktionen, inte en startpunkts thunk-funktion. Mer information finns i Double Thunking. Alternativen /clr:pure och /clr:safe compiler är inaktuella i Visual Studio 2015 och stöds inte i Visual Studio 2017.

/clr (Common Language Runtime Compil) innebär att alla funktioner och funktionspekare är __clrcall och kompilatorn tillåter inte att en funktion i kompilatorn markeras med något annat än __clrcall. När /clr:pure används kan __clrcall endast anges på funktionspekare och externa deklarationer.

Du kan anropa __clrcall funktioner direkt från befintlig C++-kod som kompilerats med hjälp av /clr så länge funktionen har en MSIL-implementering. __clrcall funktioner kan inte anropas direkt från funktioner som har infogad asm och anropa CPU-specifika inbyggda funktioner, till exempel även om dessa funktioner kompileras med /clr.

__clrcall funktionspekare är endast avsedda att användas i programdomänen där de skapades. I stället för att skicka __clrcall funktionspekare mellan programdomäner använder du CrossAppDomainDelegate. Mer information finns i Programdomäner och Visual C++.

Exempel

Observera att när en funktion deklareras med __clrcall genereras kod när det behövs. till exempel när funktionen anropas.

// clrcall2.cpp
// compile with: /clr
using namespace System;
int __clrcall Func1() {
   Console::WriteLine("in Func1");
   return 0;
}

// Func1 hasn't been used at this point (code has not been generated),
// so runtime returns the address of a stub to the function
int (__clrcall *pf)() = &Func1;

// code calls the function, code generated at difference address
int i = pf();   // comment this line and comparison will pass

int main() {
   if (&Func1 == pf)
      Console::WriteLine("&Func1 == pf, comparison succeeds");
   else
      Console::WriteLine("&Func1 != pf, comparison fails");

   // even though comparison fails, stub and function call are correct
   pf();
   Func1();
}
in Func1
&Func1 != pf, comparison fails
in Func1
in Func1

Följande exempel visar att du kan definiera en funktionspekare, så att du deklarerar att funktionspekaren endast anropas från hanterad kod. På så sätt kan kompilatorn anropa den hanterade funktionen direkt och undvika den inbyggda startpunkten (dubbelt thunk-problem).

// clrcall3.cpp
// compile with: /clr
void Test() {
   System::Console::WriteLine("in Test");
}

int main() {
   void (*pTest)() = &Test;
   (*pTest)();

   void (__clrcall *pTest2)() = &Test;
   (*pTest2)();
}

Se även

Argumentöverföring och Namngivningskonventioner
nyckelord