Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом разделе описывается, как получить доступ к неуправляемым функциям и ввести несколько полей атрибутов, которые аннотируют определение метода в управляемом коде. Примеры, демонстрирующие, как создавать объявления на основе .NET для использования с вызовом платформы, см. в разделе «Маршаллирование данных с помощью вызова платформы».
Прежде чем получить доступ к неуправляемой функции DLL из управляемого кода, необходимо знать имя функции и имя библиотеки DLL, экспортируемой ею. С помощью этих сведений можно начать запись управляемого определения для неуправляемой функции, реализованной в библиотеке DLL. Кроме того, можно настроить способ, которым механизм вызова на платформе создает функцию и осуществляет передачу данных в функцию и обратно.
Замечание
Функции API Windows, которые выделяют строку, позволяют освободить строку с помощью такого метода, как LocalFree
. Вызов платформы обрабатывает такие параметры по-разному. Для вызовов платформы сделайте параметр типом IntPtr
вместо String
типа. Используйте методы, предоставляемые классом System.Runtime.InteropServices.Marshal , чтобы преобразовать тип в строку вручную и освободить его вручную.
Основы декларации
Управляемые определения для неуправляемых функций зависят от языка, как показано в следующих примерах. Дополнительные примеры кода см. в разделе "Примеры вызова платформы".
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
Чтобы применить поля DllImportAttribute.BestFitMapping, DllImportAttribute.CallingConvention, DllImportAttribute.ExactSpelling, DllImportAttribute.PreserveSig, DllImportAttribute.SetLastError или DllImportAttribute.ThrowOnUnmappableChar к объявлению Visual Basic, необходимо использовать атрибут DllImportAttribute вместо оператора Declare
.
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);
Настройка определения
Заданы они явным образом или нет, поля атрибутов активно определяют поведение управляемого кода. Вызов платформы работает в соответствии со значениями по умолчанию, заданными в различных полях, которые существуют как метаданные в сборке. Это поведение по умолчанию можно изменить, изменив значения одного или нескольких полей. Во многих случаях используется DllImportAttribute для задания значения.
В следующей таблице приведен полный набор полей атрибутов, относящихся к вызову платформы. Для каждого поля таблица содержит значение по умолчанию и ссылку на сведения об использовании этих полей для определения неуправляемых функций DLL.
Поле | Описание |
---|---|
BestFitMapping | Включает или отключает оптимальное сопоставление. |
CallingConvention | Указывает соглашение о вызове, используемое при передаче аргументов метода. По умолчанию устанавливается значение WinAPI , которое для 32-разрядных платформ на базе Intel соответствует __stdcall . |
CharSet | Управляет изменением имени и способом маршаллинга строковых аргументов в функцию. Значение по умолчанию — CharSet.Ansi . |
EntryPoint | Указывает вызываемую точку входа DLL. |
ExactSpelling | Определяет, следует ли изменить точку входа, чтобы соответствовать набору символов. Значение по умолчанию зависит от языка программирования. |
PreserveSig | Определяет, следует ли преобразовать сигнатуру управляемого метода в неуправляемую подпись, которая возвращает HRESULT и имеет дополнительный аргумент [out, retval] для возвращаемого значения. Значением по умолчанию является true (подпись не должна быть преобразована). |
SetLastError | Позволяет вызывающему объекту использовать Marshal.GetLastWin32Error функцию API, чтобы определить, произошла ли ошибка при выполнении метода. В Visual Basic используется true значение по умолчанию; в C# и C++, значение по умолчанию — false . |
ThrowOnUnmappableChar | Управляет вызовом исключения для неуправляемого символа Юникода, преобразованного в символ ANSI "?" |
Подробные справочные сведения см. в разделе DllImportAttribute.
Рекомендации по обеспечению безопасности при вызове процедур на платформе
Элементы Assert
, Deny
, и PermitOnly
перечисления SecurityAction называются модификаторами пошагового выполнения стека. Эти члены игнорируются, если они используются в качестве декларативных атрибутов в объявлениях вызова платформы и инструкциях языка определения COM-интерфейса (IDL).
Примеры вызова функций платформы
Примеры вызова платформы в этом разделе демонстрируют использование атрибута RegistryPermission
с модификаторами прохождения стека.
В следующем примере модификаторы SecurityAction, Assert
, Deny
и PermitOnly
игнорируются.
[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();
Однако модификатор Demand
в следующем примере допускается.
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
private static extern bool CallRegistryPermissionDeny();
SecurityAction модификаторы работают правильно, если они помещаются в класс, содержащий (оболочки) вызов платформы.
[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 Модификаторы также работают правильно в вложенном сценарии, где они размещаются на вызывающей стороне вызова платформы.
{
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
Примеры взаимодействия COM в этом разделе иллюстрируют использование атрибута RegistryPermission
с модификаторами пошаговой проверки стека.
В следующих объявлениях интерфейсов взаимодействия COM игнорируются модификаторы Assert
, Deny
и PermitOnly
, подобно примерам вызова платформы в предыдущем разделе.
[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();
}
Кроме того, Demand
модификатор не принимается в сценариях объявления интерфейса взаимодействия COM, как показано в следующем примере.
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]
interface IDemandStubsItf
{
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallRegistryPermission();
[FileIOPermission(SecurityAction.Demand, Unrestricted = true)]
bool CallFileIoPermission();
}