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