Megosztás a következőn keresztül:


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 WinAPI32 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 Assertenumerá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