Поиск

Преобразование и Plnvoke

Хотя вы, как правило, не замечаете преобразования и не определяете его работу, каждый раз при вызове функции DLL .NET должен преобразовать параметры для этой функции и возвращаемое значение — для вызывающего приложения .NET. В предыдущих примерах этой главы мне ничего не приходилось делать для этого, так как для каждого типа в .NET определен встроенный тип по умолчанию. Например, тип второго и третьего параметров функций MessageBoxA и MessageBox допределен как строковый. Однако компилятору С# известно, что эквивалентом строки С# является Win32 LPSTR. А если вам захочется изменить поведение при преобразовании, установленное .NET по умолчанию? Для этого служит атрибут MarshallAs, который также определен в пространстве имен System. Runtime. InteropServices.

В следующем примере я снова применю MessageBox во избежание излишнего усложнения. Здесь я выбрал Unicode-версию Щп32-функции
MessageBox. Как вам уже известно, мне требуется задать перечисление CharSet. Unicode для именованного параметра CharSet атрибута Dlllmport. Однако в этом случае я хочу, чтобы компилятор преобразовывал данные в "широкие" символы (LPWSTR), поэтому я использую атрибут Marshal-As и задаю с перечислением UnmanagedType тип, в который я хочу конвертировать мой собственный тип. Вот этот код:

using System;
using System.Runtime.InteropServices;
class PInvoke4App {
[Dlllmport("user32.dll", CharSet=CharSet.Unicode)]
static extern int MessageBox(int hWnd,
[MarshalAs(UnmanagedType.LPWStr)]
string msg,
[MarshalAs(UnmanagedType.LPWStr)]
string caption,
int type);
public static void Main() <
MessageBox(0,
"Hello, World!",
"This is called from a C# app!", 0); } }

Атрибут MarshalAs может быть прикреплен к параметрам метода (как в этом примере), возвращаемым значениям метода и полям структур или классов. Заметьте также: чтобы изменить преобразование по умолчанию возвращаемого значения метода, прикрепите атрибут MarshalAs к самому методу.