14_C#_PInvoke

advertisement
Атрибут DllImport
 Platform Invocation Services (PInvoke) поддерживает средства для вызова кода
неуправляемых функций, которые находятся в DLL.
 При вызове неуправляемой функции из DLL компилятор C# должен иметь
информацию
• о прототипе неуправляемой функции;
• в какой Dll-библиотеке находится функция;
• как передаются параметры и возвращаемое значение.
 Атрибут DllImport дает возможность связать статический метод класса с
внешними функциями из DLL.
[AttributeUsage(AttributeTargets.Method)]
public sealed class DllImportAttribute : Attribute
 Атрибут DllImport имеет один обязательный параметр типа string – имя
библиотеки динамической компоновки.
 Остальные параметры атрибута – необязательные (именованные).
Сервис PInvoke
 Platform Invocation Services (PInvoke) использует метаданные для поиска
экспортируемой функции и маршалинга параметров в период выполнения.
Рисунок из раздела MSDN – A Closer Look at Platform Invoke
 Platform Invocation Services (PInvoke) загружает Dll-библиотеку в память,
размещает параметры в стеке, передает исключения из неуправляемого кода в
управляемый.
Взаимодействие управляемого и неуправляемого кода
Sonja Keserovic, David
Mortenson, Adam Nathan
An Overview of
Managed/Unmanaged Code
Interoperability
Microsoft Corporation, October
2003
Атрибут DllImport. Пример
using System;
using System.Runtime.InteropServices;
namespace PInvoke_Demo
{ class Class1
{ static void Main(string[] args)
{ bool res;
try
{ double par1 = 3;
double par2 = 0;
res = F1(par1, ref par2);
}
catch (System.Runtime.InteropServices.ExternalException ex )
{ Console.WriteLine(ex.Message);}
}
[DllImport("DLL_ForCSharp.dll")]
public static extern bool F1(double par1, ref double par2);
}}
Атрибут DllImport. Пример. Код C++
extern "C“ { _declspec(dllexport) bool F1(double d1, double& d2)
{
if ( d1<100)
{d2 = d1*2;
d1 = -1;
}
else throw 1;
return true;
}}
 При создании Dll-файла компоновщик добавляет в исполняемый код раздел
экспорта – таблицу экспортируемых функций.
Экспортируемая функция
• либо имеет модификатор _declspec(dllexport);
• либо находится в разделе EXPORTS файла определения модуля (*.def);
 extern “C” – спецификация для компоновщика, определяет соглашения о
вызове функций (calling convention).
 Список функций, которые экспортирует Dll, можно посмотреть с помощью
утилиты dumpbin.exe. Каталог
Program Files \ Microsoft Visual Studio 8 \ VC \ bin
Именованные параметры атрибута DllImport
 Некоторые именованные параметры атрибута DllImport:
string EntryPoint
Имя входной точки в Dll-библиотеке. По умолчанию –
имя метода, к которому прикреплен атрибут.
CallingConvention
CallingConvention
Значение перечисления CallingConvention, которое
определяет соглашение о вызове функций, используемое
для входной точки Dll-библиотеки. По умолчанию –
CallingConvention. WinAPI.
CharSet CharSet
Значение перечисления CharSet, которое определяет
набор символов, используемых во входной точке Dllбиблиотеки. По умолчанию – CharSet.Auto, т.е. при
маршалинге в зависимости от OC выбирается Unicode
или ANSI.
bool ExactSpelling
Умолчание false. При значении true EntryPoint должно
точно совпадать с именем точки входа (для Win32 API).
CallingConvention
 Значение параметра CallingConvention определяет соглашение о вызове
функций, используемое для входной точки Dll-библиотеки. Значение
параметра должно отвечать тому соглашению, которое использовалось при
компиляции библиотеки.
 Соглашение о вызове функций определяет
• порядок, в котором параметры функции размещаются в стеке;
• какая из функций – вызывающая или вызываемая - удаляет параметры
из стека при завершении вызова;
• внутреннее имя для функции ( decorated name).
 При создании Dll-библиотеки соглашения о вызове функции определяются
опциями компилятора, которые устанавливают соглашения для всех функций,
для которых они не указаны явно.
 В коде C/C++ можно явно указать соглашения с помощью ключевых слов
__cdecl
__stdcall
__fastcall
CallingConvention -2
 Значения перечисления CallingConvention
Cdecl
Соглашения С
StdCall
Соглашения Win32 API (умолчание при вызове неуправляемого
метода)
ThisCall
Соглашения С++ для методов классов
Winapi
Умолчание для платформы, например, Cdecl для Windows CE.
FastCall
.Net Framework 2.0 не поддерживается.
Атрибут MarshalAs
 Атрибут MarshalAs определяет, как передаются данные между управляемым и
неуправляемым кодом. Используется в основном при взаимодействии с COMобъектами.
 Для каждого примитивного .NET типа есть принятый по умолчанию
соответствующий тип в неуправляемом коде. Атрибут MarshalAs дает
возможность переопределить эти соглашения.
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter |
AttributeTargets.ReturnValue)]
public sealed class MarshalAsAttribute : Attribute
 Атрибут MarshalAs имеет один обязательный параметр – значение
перечисления UnmanagedType и 7 именованных (необязательных).
 Перечисление UnmanagedType имеет более 30 полей.
Copying and pinning
 Маршалинг (marshaling) – упаковка данных в стандартный формат для
обмена между COM-объектами.
 При маршалинге данные могут копироваться (copying) или прикрепляться
(pinning).
copying
(копирование)
interop marshaler копирует данные из одной области
памяти в другую.
pinning
(прикрепление)
данные в управляемой куче временно фиксируются (их
не перемещает сборщик мусора). По сравнению с
копированием это более быстрый способ передачи
данных.
 Способ маршалинга определяется типом данных.
Маршалинг типов-значений
 Для типов-значений всегда выполняется копирование.
Рисунок из раздела MSDN - Copying and Pinning
Маршалинг ссылочных типов по значению
 Для ссылочных типов, которые передаются по значению, может
выполняться копирование или прикрепление.
Рисунок из раздела MSDN - Copying and Pinning
Blittable типы
 Типы, которые имеют одинаковое представление в управляемой и
неуправляемой памяти, и не требуют преобразования при передаче из
управляемого кода в неуправляемый, называются blittable.
 Прикрепление (pinning) при маршалинге выполняется только для blittable
типов.
blittable типы:
System.Byte
System.Int32
System.IntPtr
System.SByte
System.UInt32
System.UIntPtr
System.Int16
System.Int64
System.UInt16
одномерные массивы из элементов blittable-типов.
System.String и System.Boolean - non-blittable типы.
Маршалинг типа bool
 Данные типа bool имеют разные представления в неуправляемом коде.
Если явно не указан атрибут MarshalAs , по умолчанию используется
значение UnmanagedType.Bool.
Значение перечисления
UnmanagedType
Формат в неуправляемом коде
UnmanagedType.Bool
4-байтовое целое значение, любое ненулевое значение
трактуется как TRUE, 0 как FALSE.
UnmanagedType.U1
1-байтовое целое значение, значение 1 используется для TRUE,
0 для FALSE. Используется для типа bool в C++.
UnmanagedType.VariantBool
2-байтовое целое значение, где значение -1 используется для
TRUE, 0 для FALSE.
Маршалинг строк
 Типы, которые передаются по значению, по умолчанию передаются как Inпараметры.
 Исключение – System.Text.StringBuilder. Когда объекты этого типа
передаются по значению, код получает доступ к внутреннему буферу с
массивом символов. Неуправляемый код может изменять символы, но не
может выходить за границы массива.
 Строки System.String всегда копируются в промежуточный буфер.
Маршалинг ссылочных типов по ссылке
 Для ссылочных типов, которые передаются по ссылке, всегда выполняется
копирование.
Рисунок из раздела MSDN - Copying and Pinning
Download