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 LocalFree
je 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 false vý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
, Deny
a 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 SecurityActionAssert
jsou modifikátory , Deny
a 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
, Deny
a 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();
}