Совмещение управляемого и неуправляемого кодов
Пример. Указание набора символов в C#
Поле DllImportAttribute.CharSet определяет набор символов как базовый набор ANSI или Unicode. Набор символов определяет режим выполнения маршалинга строковых аргументов. Для указания набора символов применяется один из следующих вариантов атрибута:
[DllImport("dllname", CharSet=CharSet.Ansi)]
[DllImport("dllname", CharSet=CharSet.Unicode)]
[DllImport("dllname", CharSet=CharSet.Auto)]В следующем примере показаны три управляемых определения функции MessageBox с атрибутами, задающими наборы символов. В первом определении, в котором значение поля CharSet не задано, по умолчанию принимается набор символов ANSI:
[DllImport("user32.dll")]
public static extern int MessageBoxA(int hWnd, String text,
String caption, uint type);
[DllImport("user32.dll", CharSet=CharSet.Unicode)]
public static extern int MessageBoxW(int hWnd, String text,
String caption, uint type);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int MessageBox(int hWnd, String text,
String caption, uint type);Примеры платформного вызова. MessageBox, Beep, PlaySound
Под ПЛАТФОРМОЙ НАЗНАЧЕНИЯ понимается платформа, которой предназначена закодированная в атрибутах информация. Естественно, это .NET.
В других платформах службы платформного вызова нет. Никакая другая платформа просто не сумеет прочитать и понять значение полей атрибутов.
Ниже демонстрируется определение и вызов функции MessageBox из библиотеки User32.dll. В качестве аргумента передается простая строка. Значение для атрибута поля DllImportAttribute.CharSet установлено в Auto. Это позволяет платформе назначения самостоятельно определять размер символов и выбирать маршалинг строк:
using System.Runtime.InteropServices;
public class Win32 {
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int MessageBox(int hWnd, String text,
String caption, uint type);
}
public class HelloWorld {
public static void Main() {
Win32.MessageBox(0, "Hello World", "Platform Invoke Sample", 0);
}
}Информация о функции Beep в хелпах по C# отсутствует. Такой функции в .NET НЕТ. Однако способы заставить C#-приложение "пропищать" все же существуют (передача функции Console.Writeline параметра с соответствующей escape-последовательностью не в счет).
Beep
обеспечивает генерацию simple tones (простых звуков) на спикере. Функция выполняется синхронно; она не возвращает управления до тех пор, пока не завершится звучание.
BOOL Beep( DWORD dwFreq, DWORD dwDuration );
Параметры
dwFreq
Частотная характеристика звука в герцах. Диапазон значений этого параметра ограничен следующими величинами 37–32,767 ( 0x25– 0x7FFF ).
В Windows Me/98/95 функция Beep этот параметр игнорирует.
dwDuration
Продолжительность звучания в миллисекундах.
В Windows Me/98/95 функция Beep этот параметр игнорирует.
Здесь речь идет о неуправляемой функции, судя по всему, реализованной в C++. Так вот, при успешном выполнении функция возвращает ненулевое значение. В C++ такие значения соответствуют значению ИСТИНА.
В противном случае возвращается нулевое значение, то есть ЛОЖЬ:
using System;
using System.Threading;
using System.Runtime.InteropServices;
namespace BeepByWin32API
{
// Import a Beep() API function.
class Class1
{
// Таким образом получаем возможность использования импортируемых
// функций в приложении .NET.
[DllImport("kernel32.dll")]
private static extern bool Beep(int frec, int dur);
// Импортируется функция PlaySound().
[DllImport("winmm.dll")]
public static extern bool PlaySound(string pszSound,
int hmod,
int fdwSound);
// Константы, необходимые для использования PlaySound...
public const int SND_FILENAME = 0x00020000;
// За конкретное значение параметра я не ручаюсь. Подобрал сам.
// Играет - и ладно...
public const int SND_ASYNC = 0x0010;//0x0001;
// The main entry Point for the application.
static void Main(string[] args)
{
int i;
// Извлекаем звук посредством escape-последовательности.
Console.WriteLine("Пропищим..." + "\a\a\a\a\a\a\a\a\a\a");
Console.WriteLine("И еще...");
for (i = 0; i < 10; i++) {Console.Write("\a"); Thread.Sleep(1000);}
Console.WriteLine("Нажми Any Key для продолжения опытов...");
Console.ReadLine();
// Извлекаем звук посредством обращения к функции API Beep().
// Frequency of the sound, in hertz.
// This parameter must be in the range 37 through 32,767 (0x25 through 0x7FFF).
// Duration of the sound, in milliseconds.
Beep(800,200);
Beep(500,1000);
Beep(100,500);
Beep(1000,2000);
Beep(0x25,2000);
Beep(0x7FFF,2000);
Console.WriteLine("Нажми Any Key для продолжения опытов...");
Console.ReadLine();
for (i = 0; i < 10; i++)
{
PlaySound("Trumpet1.wav", 0, SND_FILENAME|SND_ASYNC);
}
}
}
}
Листинг
14.2.