Шаг 214.
Microsoft Visual C++ 2010. Язык С/С++. Преобразование между регулируемыми и нерегулируемыми... . Пример 3. Преобразование String^ строки в строку wchar_t

    На этом шаге мы приведем программу, реализующую указанное преобразование.

    Тип wchar_t - это native-тип символа по таблице Юникода. Этот тип данного отличается от типа char тем, что символ кодируется двумя байтами, а не одним. Класс String тоже создает строку из Юникод-символов, однако по своему определению относится к managed-типу.

    Преобразование, которое мы рассматриваем, фактически переводит Юникод-строку из состояния managed в состояние native. А в этом состоянии со строкой уже можно работать, применяя обычный указатель *. Юникод-тексты можно вводить в файлы и читать из них соответственно функциями fputws() и fgetws.

    Текст программы приведен ниже, а результат - на рисунке 1.

// 214_1.cpp: главный файл проекта.

#include "stdafx.h"

#include <stdio.h> //для printf()
#include <conio.h> //для _getch() 
#include <vcclr.h> //для PtrToStringChars()

using namespace System;
using namespace System::Runtime::InteropServices;

#pragma unmanaged
void NativeTakesAString(const wchar_t* p)
{
	printf("(native) recieved '%S'\n", p);
}
#pragma managed

void main()
{
	String^ s = gcnew String("test string"); 
	pin_ptr<const wchar_t> str = PtrToStringChars(s);

	// метод размещает s в управляемой куче и выдает 
	// native-указатель типа _const_Char_ptr на 
	// размещенный объект. Этот указатель с помощью оператора
	// [cli::]pin_ptr<cv_qualifier type> var = ^initializer; 
	// преобразуется в тип const wchar_t. 
	// Здесь:
	// cv_qualifier - квалификатор const или квалификатор volatile. 
	// Квалификатор volatile показывает, что поле может 
	// модифицироваться многочисленными средами, выполняющимися в 
	// данный момент, и все изменения данного поля будут 
	// присутствовать в этом поле. Указатель типа pin_ptr по 
	// умолчанию имеет квалификатор volatile, поэтому в операторе 
	// применен квалификатор const, чтобы объект в куче не изменял 
	// своего значения, а не только место расположения.
	// initializer - это ссылочный тип данного: элемент 
	// managed-массива или любого другого объекта, которому 
	// вы назначаете native-указатель.
	// Метод PtrToStringChars() как раз и выдает такой указатель:
	// native-указатель в управляемой (managed) куче.
	// type - тип initializer'а. В нашем случае это wchar_t 
	// var - это имя pin_ptr указателя. В нашем случае это
	// str. Т.е. str - это уже native-указатель String в 
	// управляемой куче.

	Console::WriteLine("(managed) passing string to native func...");
	// вывод сообщения из managed-функции
	NativeTakesAString( str );
	// вызов native-функции, которая выдаст native-сообщение
	_getch();
}
Архив проекта можно взять здесь.


Рис.1. Результат преобразования Юникод-строки в native-строку

    Здесь применен указатель pin_ptr (указатель от зашкаливания, как определяют его авторы). Это внутренний указатель, который оберегает объект (на который он указывает) от какого-либо перемещения в управляемой куче (памяти, с которой работает режим CLR): значение указателя не изменяется средой CLR. Такое условие необходимо при передаче адреса managed-объекта native-функции, потому что этот адрес не должен меняться во время вызова native-функции.

    На следующем шаге мы приведем пример программы, выполняющей преобразование строки wchar_t в строку String^.




Предыдущий шаг Содержание Следующий шаг