Vytváření prototypů ve spravovaném kódu

Toto téma popisuje, jak získat přístup k nespravovaným funkcím a představuje několik polí atributů, která přiřazují definici metody ve spravovaném kódu. Příklady, které demonstrují, jak sestavit . Deklarace založené na platformě, které se mají použít s voláním platformy, najdete v tématu Marshalling Data with Platform Invoke.

Než budete mít přístup k nespravované funkci KNIHOVNY DLL ze spravovaného kódu, musíte znát název funkce a název knihovny DLL, která ji exportuje. S těmito informacemi můžete začít psát spravovanou definici pro nespravovanou funkci, která je implementována v knihovně DLL. Kromě toho můžete upravit způsob, jakým volání platformy vytvoří funkci a zařazuje data do a z této funkce.

Poznámka:

Funkce rozhraní API systému Windows, které přidělují řetězec, umožňují uvolnit řetězec pomocí metody, jako LocalFreeje například . Volání platformy zpracovává tyto parametry odlišně. Pro volání platformy vytvořte parametr jako IntPtr typ místo String typu. Pomocí metod poskytovaných System.Runtime.InteropServices.Marshal třídou převeďte typ na řetězec ručně a ručně jej uvolněte.

Základy deklarace

Spravované definice nespravovaných funkcí jsou závislé na jazyce, jak je vidět v následujících příkladech. Kompletní příklady kódu najdete v tématu Příklady volání platformy.

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

Chcete-li použít DllImportAttribute.BestFitMapping, , DllImportAttribute.CallingConvention, DllImportAttribute.ExactSpelling, DllImportAttribute.PreserveSigDllImportAttribute.SetLastErrornebo DllImportAttribute.ThrowOnUnmappableChar pole na deklaraci jazyka Visual Basic, je nutné použít DllImportAttribute atribut místo Declare příkazu.

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);

Úprava definice

Bez ohledu na to, jestli je nastavíte explicitně nebo ne, pole atributů jsou v práci definující chování spravovaného kódu. Volání platformy funguje podle výchozích hodnot nastavených v různých polích, která existují jako metadata v sestavení. Toto výchozí chování můžete změnit úpravou hodnot jednoho nebo více polí. V mnoha případech použijete DllImportAttribute k nastavení hodnoty.

Následující tabulka uvádí kompletní sadu polí atributů, která se týkají volání platformy. Pro každé pole tabulka obsahuje výchozí hodnotu a odkaz na informace o tom, jak tato pole použít k definování nespravovaných funkcí knihovny DLL.

Pole Popis
BestFitMapping Povolí nebo zakáže mapování, které nejlépe vyhovuje.
CallingConvention Určuje konvenci volání, která se má použít při předávání argumentů metody. Výchozí hodnota je WinAPI, která odpovídá __stdcall 32bitovým platformám intel.
CharSet Řídí mangling názvu a způsob, jakým by měly být argumenty řetězce zařazovány do funkce. Výchozí hodnota je CharSet.Ansi.
EntryPoint Určuje vstupní bod knihovny DLL, který se má volat.
ExactSpelling Určuje, zda má být vstupní bod upraven tak, aby odpovídal znakové sadě. Výchozí hodnota se liší podle programovacího jazyka.
PreserveSig Určuje, jestli má být podpis spravované metody transformován na nespravovaný podpis, který vrací hodnotu HRESULT, a má další argument [out, retval] pro návratovou hodnotu.

Výchozí hodnota je true (podpis by neměl být transformován).
SetLastError Umožňuje volajícímu použít Marshal.GetLastWin32Error funkci rozhraní API k určení, jestli při provádění metody došlo k chybě. V jazyce Visual Basic je výchozí hodnota true: v jazyce C# a C++ je falsevýchozí hodnota .
ThrowOnUnmappableChar Ovládací prvky vyvolání výjimky u nemapovatelného znaku Unicode, který je převeden na znak ANSI "?".

Podrobné referenční informace naleznete v tématu DllImportAttribute.

Aspekty zabezpečení vyvolání platformy

Assert, Denya PermitOnly členy výčtu SecurityAction jsou označovány jako modifikátory chodu zásobníku. Tyto členy se ignorují, pokud se používají jako deklarativní atributy v deklarativních deklaracích volání platformy a příkazů IDL (COM Interface Definition Language).

Příklady vyvolání platformy

Ukázky vyvolání platformy v této části ilustrují použití RegistryPermission atributu s modifikátory zásobníku walk.

V následujícím příkladu SecurityActionAssertjsou modifikátory , Denya PermitOnly modifikátory ignorovány.

[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();  

Modifikátor v následujícím příkladu Demand je však přijat.

[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]  
    private static extern bool CallRegistryPermissionDeny();  

SecurityAction modifikátory fungují správně, pokud jsou umístěny do třídy, která obsahuje (zalamuje) volání vyvolání platformy.

      [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 modifikátory také fungují správně ve vnořeném scénáři, kde jsou umístěny na volajícím volání vyvolání platformy:

      {  
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();  
    }  
}  

Příklady zprostředkovatele komunikace s objekty COM

Ukázky zprostředkovatele komunikace modelu COM v této části znázorňují použití RegistryPermission atributu s modifikátory zásobníku walk.

Následující deklarace rozhraní zprostředkovatele komunikace modelu COM ignorují Assert, Denya PermitOnly modifikátory, podobně jako platforma vyvolat příklady v předchozí části.

[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();  
}  

Kromě toho Demand modifikátor není přijat ve scénářích deklarací rozhraní zprostředkovatele komunikace modelu COM, jak je znázorněno v následujícím příkladu.

[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]  
interface IDemandStubsItf  
{  
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]  
    bool CallRegistryPermission();  
[FileIOPermission(SecurityAction.Demand, Unrestricted = true)]  
    bool CallFileIoPermission();  
}  

Viz také