Prototípusok létrehozása felügyelt kódban
Ez a témakör bemutatja, hogyan érheti el a nem felügyelt függvényeket, és hogyan vezet be több attribútummezőt, amelyek a felügyelt kód metódusdefinícióját jegyzetelik. Példák a konstruktálásra. A platformhíváshoz használandó NET-alapú deklarációkat lásd: Adatok platformhívással történő rendezése.
Ahhoz, hogy egy felügyelt kódból elérhessen egy nem felügyelt DLL-függvényt, ismernie kell a függvény nevét és az azt exportáló DLL nevét. Ezzel az információval megkezdheti egy DLL-ben implementált nem felügyelt függvény felügyelt definíciójának megírását. Emellett beállíthatja, hogy a platformhívás hogyan hozza létre a függvényt, és az adatokat a függvénybe és azokból hozza létre.
Feljegyzés
A sztringet lefoglaló Windows API-függvények lehetővé teszik, hogy a sztringet egy olyan módszerrel szabadíthassa fel, mint a LocalFree
. A platformhívás eltérően kezeli az ilyen paramétereket. Platformhívások esetén a paramétert IntPtr
típus helyett típusként String
kell megadni. Az osztály által System.Runtime.InteropServices.Marshal biztosított metódusokkal manuálisan konvertálhatja a típust sztringgé, és manuálisan szabadíthatja fel.
A deklarálás alapjai
A nem felügyelt függvények felügyelt definíciói nyelvfüggőek, ahogy az alábbi példákban is látható. További teljes kód példákért lásd a platformhívási példákat.
Friend Class NativeMethods
Friend Declare Auto Function MessageBox Lib "user32.dll" (
ByVal hWnd As IntPtr,
ByVal lpText As String,
ByVal lpCaption As String,
ByVal uType As UInteger) As Integer
End Class
Ha a DllImportAttribute.BestFitMapping, DllImportAttribute.CallingConvention, , DllImportAttribute.ExactSpellingDllImportAttribute.PreserveSig, DllImportAttribute.SetLastErrorvagy DllImportAttribute.ThrowOnUnmappableChar mezőket egy Visual Basic-deklarációra szeretné alkalmazni, az utasítás helyett az DllImportAttributeDeclare
attribútumot kell használnia.
Imports System.Runtime.InteropServices
Friend Class NativeMethods
<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Friend Shared Function MessageBox(
ByVal hWnd As IntPtr,
ByVal lpText As String,
ByVal lpCaption As String,
ByVal uType As UInteger) As Integer
End Function
End Class
using System;
using System.Runtime.InteropServices;
internal static class NativeMethods
{
[DllImport("user32.dll")]
internal static extern int MessageBox(
IntPtr hWnd, string lpText, string lpCaption, uint uType);
}
using namespace System;
using namespace System::Runtime::InteropServices;
[DllImport("user32.dll")]
extern "C" int MessageBox(
IntPtr hWnd, String* lpText, String* lpCaption, unsigned int uType);
A definíció módosítása
Akár explicit módon, akár nem állítja be őket, az attribútummezők a felügyelt kód viselkedését határozzák meg. A platformhívás a szerelvény metaadataiként létező különböző mezőkben beállított alapértelmezett értékek szerint működik. Ezt az alapértelmezett viselkedést egy vagy több mező értékének módosításával módosíthatja. Sok esetben az érték beállításához használja az DllImportAttribute értéket.
Az alábbi táblázat a platformhíváshoz kapcsolódó attribútummezők teljes készletét sorolja fel. Minden mező esetében a tábla tartalmazza az alapértelmezett értéket, valamint egy hivatkozást, amely arra vonatkozó információt tartalmaz, hogy miként definiálhatók ezek a mezők a nem felügyelt DLL-függvények definiálásához.
Mező | Leírás |
---|---|
BestFitMapping | Engedélyezi vagy letiltja a legjobban illeszkedő leképezést. |
CallingConvention | Megadja a metódusargumentumokban használandó hívási konvenciót. Az alapértelmezett érték a WinAPI 32 bites Intel-alapú platformoknak megfelelő __stdcall . |
CharSet | Szabályozza a névkezelést és a sztringargumentumok függvényhez való rendezési módját. Az alapértelmezett érték CharSet.Ansi . |
EntryPoint | Megadja a meghívandó DLL-belépési pontot. |
ExactSpelling | Azt határozza meg, hogy a belépési pontot a karakterkészletnek megfelelően kell-e módosítani. Az alapértelmezett érték programozási nyelvtől függően változik. |
PreserveSig | Azt szabályozza, hogy a felügyelt metódus aláírása nem felügyelt aláírássá legyen-e alakítva, amely HRESULT értéket ad vissza, és a visszatérési értékhez további [out, retval] argumentumot tartalmaz. Az alapértelmezett érték true (az aláírást nem szabad átalakítani). |
SetLastError | Lehetővé teszi a hívó számára, hogy az Marshal.GetLastWin32Error API-függvény használatával állapítsa meg, hogy hiba történt-e a metódus végrehajtása során. A Visual Basicben az alapértelmezett érték true ; a C# és a C++, az alapértelmezett érték a false . |
ThrowOnUnmappableChar | Olyan kivételt eredményező vezérlők, amelyek ansi "?" karakterré konvertált, nem alkalmazható Unicode-karakterre kerülnek. |
Részletes referenciainformációkért lásd: DllImportAttribute.
Platformhívási biztonsági szempontok
Az Assert
enumerálás , Deny
és PermitOnly
tagjait SecurityAction veremjárásmódosítóknak nevezzük. Ezek a tagok figyelmen kívül lesznek hagyva, ha deklaratív attribútumként használják őket a platformhívási deklarációkban és a COM Interface Definition Language (IDL) utasításokban.
Platformhívási példák
A jelen szakaszban szereplő minták meghívása RegistryPermission
a platformon az attribútum használatát mutatja be a stack walk modifiers használatával.
Az alábbi példában a rendszer figyelmen kívül hagyja a SecurityActionAssert
, Deny
és PermitOnly
a módosítókat.
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
private static extern bool CallRegistryPermissionAssert();
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Deny, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.PermitOnly, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
A Demand
következő példában szereplő módosító azonban elfogadott.
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
SecurityAction a módosítók megfelelően működnek, ha egy olyan osztályba kerülnek, amely tartalmazza (burkolja) a platformhívás hívását.
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
public ref class PInvokeWrapper
{
public:
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
private static extern bool CallRegistryPermissionDeny();
};
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
class PInvokeWrapper
{
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
private static extern bool CallRegistryPermissionDeny();
}
SecurityAction a módosítók megfelelően működnek beágyazott forgatókönyvekben is, ahol a platformhívás hívásának hívójára kerülnek:
{
public ref class PInvokeWrapper
public:
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
private static extern bool CallRegistryPermissionDeny();
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
public static bool CallRegistryPermission()
{
return CallRegistryPermissionInternal();
}
};
class PInvokeScenario
{
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
private static extern bool CallRegistryPermissionInternal();
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
public static bool CallRegistryPermission()
{
return CallRegistryPermissionInternal();
}
}
COM interop példák
Az ebben a szakaszban található COM-interop minták az attribútum használatát RegistryPermission
szemléltetik a verem sétamódosítóival.
Az alábbi COM interop felületi deklarációk figyelmen kívül hagyják a Assert
, Deny
és PermitOnly
módosítókat, hasonlóan az előző szakaszban szereplő platformhívási példákhoz.
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IAssertStubsItf
{
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Assert, Unrestricted = true)]
bool CallFileIoPermission();
}
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IDenyStubsItf
{
[RegistryPermission(SecurityAction.Deny, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Deny, Unrestricted = true)]
bool CallFileIoPermission();
}
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IAssertStubsItf
{
[RegistryPermission(SecurityAction.PermitOnly, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.PermitOnly, Unrestricted = true)]
bool CallFileIoPermission();
}
Emellett a Demand
módosító nem fogadható el a COM interop felületi deklarálási forgatókönyvekben, ahogy az az alábbi példában is látható.
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IDemandStubsItf
{
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallFileIoPermission();
}
Lásd még
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: