logo search
CSharp_Prog_Guide

Передача структур

Для многих неуправляемых функций в качестве параметра должны быть переданы члены структур (в Visual Basic это определяемые пользователем типы) или члены классов, определяемые в управляемом коде программы. Для сохранения исходного размещения и выравнивания при передаче структур или классов в неуправляемый код необходимо предоставить дополнительные сведения при вызове неуправляемого кода. В этом разделе описывается атрибут StructLayoutAttribute, который можно использовать для определения форматированных типов. Для управляемых структур и классов можно выбрать одно из стандартных размещений, предоставленных перечислением LayoutKind.

Важнейшим из понятий, описанных в этом разделе, является существенное различие между структурами и классами как типами. Структуры представляют собой типы значений, а классы — ссылочные типы, которые всегда обеспечивают, по крайней мере, один уровень косвенного обращения к памяти (указатель на значение). Это различие очень важно, так как неуправляемые функции часто требуют косвенного обращения, что видно из примеров подписей в первом столбце следующей таблицы. Объявления управляемых структур и классов в остальных столбцах показывают, насколько возможна настройка уровня косвенного обращения в объявлении.

Неуправляемая подпись

Управляемое объявление:

без косвенного обращения

struct MyStruct(…);

Управляемое объявление:

один уровень косвенного обращения

class MyStruct(…);

DoWork(MyStruct x);

Требует отсутствия уровней косвенного обращения.

DoWork(ByVal x As MyStruct)

Добавляет ноль уровней косвенного обращения.

Невозможно, так как уже существует один уровень косвенного обращения.

DoWork(MyStruct* x);

Требует одного уровня косвенного обращения.

DoWork(ByRef x As MyStruct)

Добавляет один уровень косвенного обращения.

DoWork(ByVal x As MyStruct)

Добавляет ноль уровней косвенного обращения.

DoWork(MyStruct** x);

Требует двух уровней косвенного обращения.

Невозможно, так как объявление ByRef ByRef использовать нельзя.

DoWork(ByRef x As MyStruct)

Добавляет один уровень косвенного обращения.

The table describes the following guidelines for platform invoke declarations:

Declaring and Passing Structures

The following example shows how to define the Point and Rect structures in managed code, and pass the types as parameter to the PtInRect function in the User32.dll file. PtInRect has the following unmanaged signature:

BOOL PtInRect(const RECT *lprc, POINT pt);

Notice that you must pass the Rect structure by reference, since the function expects a pointer to a RECT type.

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]

public struct Point {

public int x;

public int y;

}

[StructLayout(LayoutKind.Explicit)]

public struct Rect {

[FieldOffset(0)] public int left;

[FieldOffset(4)] public int top;

[FieldOffset(8)] public int right;

[FieldOffset(12)] public int bottom;

}

class Win32API {

[DllImport("User32.dll")]

public static extern bool PtInRect(ref Rect r, Point p);

}

Эта таблица содержит следующие указания для объявлений вызовов неуправляемого кода: