Совмещение управляемого и неуправляемого кодов
Пример. Указание набора символов в 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.