pkfox Ответов: 1

Проблема с std:: wstring


Привет всем, ниже код компилируется и работает прекрасно по сравнению с 2013 годом, но когда я пытаюсь скомпилировать его с помощью G++ на Linux коробки я получаю множество ошибок, связанных с использованием std::wstring, которая, я знаю, что это проблема, а если я заменю все wstring и wostringstream с строкой и ostringstream соответственно все хорошо. Это всего лишь личный проект и поэтому очень грубый на данный момент.

#include <vector>
#include <string>
#include <time.h>
#include <iostream>
#include <sstream>
#include <map>
#include "squeezemessage.h"
#include <random>

#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <cpprest/json.h>

using namespace utility;                    // Common utilities like string conversions
using namespace web;                        // Common features like URIs.
using namespace web::http;                  // Common HTTP functionality
using namespace web::http::client;          // HTTP client features
using namespace concurrency::streams;       // Asynchronous streams

int ResultCount = 0;
std::vector<std::pair<std::wstring, std::wstring>> Artists;

void GetJsonResponse(json::value &jsonValue, http_response &response)
{
	jsonValue = response.extract_json().get().at(U("result"));
	ResultCount = jsonValue.size();
}

void SetRequest(http_request &requester, std::wstring &SqueezeMsg)
{
	requester.set_method(methods::POST);
	requester.headers().set_content_type(L"application/json");
	requester.set_body(SqueezeMsg);
}

std::wstring GetClient()
{
	return L"http://10.10.1.11:9000/jsonrpc.js";
}


pplx::task<void> Post(std::wstring SqueezeMsg)
{
	http_request requester;
	SetRequest(requester, SqueezeMsg);
	Artists.clear();

	return pplx::create_task([requester]
	{
		std::wstring URL(GetClient());

		http_client client(URL);

		return client.request(requester);

	}).then([](http_response response)
	{
		int code = response.status_code();

		if (response.status_code() == status_codes::OK)
		{
			json::value jsonValue;
			GetJsonResponse(jsonValue, response);

			std::map<std::wstring, std::wstring> Entities;

			Entities.insert(std::pair<std::wstring, std::wstring>(U("contributors_loop"),U("contributor")));
			Entities.insert(std::pair<std::wstring, std::wstring>(U("albums_loop"),U("album")));
			Entities.insert(std::pair<std::wstring, std::wstring>(U("tracks_loop"),U("track")));	
			
			std::wostringstream ss;

			if (ResultCount > 0)
			{
				ResultCount = 0;

				std::map<std::wstring, std::wstring>::iterator it;

				for (it = Entities.begin(); it != Entities.end(); ++it)
				{
					if (jsonValue.has_field(it->first))
					{
						json::value EntityArray = jsonValue.at(it->first);
						std::wstring FieldName(it->second);

						for (size_t i = 0; i < EntityArray.size(); i++)
						{
							std::wostringstream ss;
							ss << FieldName << ": " << (i + 1);
							std::wstring whatever(EntityArray[i].at(FieldName).as_string());
							Artists.push_back(std::pair<std::wstring, std::wstring>(ss.str(), whatever));
							ResultCount++;
						}
					}
				}
			}
		}
	});
}

int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		std::wcout << L"\n\nUsage: " << argv[0] << L" search term\n";
		return -1;
	}

	SqueezeMessage Squeezer;
	std::wostringstream ss;
	ss << L"term:" << argv[1];
	
	std::wstring SearchTerm(ss.str());

	Squeezer.BuildMessage(L"search", L"0", L"10000", SearchTerm);
	std::wstring SqueezeMsg = Squeezer.SqueezeRequestW;
	std::wcout << L"\n\n*** Running query " << SqueezeMsg << L"\n";

	Post(SqueezeMsg).get();

	for (std::vector<std::pair<std::wstring, std::wstring>>::iterator it = Artists.begin(); it != Artists.end(); ++it)
		std::wcout << it->first << ":" << it->second << '\n';

	std::wcout << L"\n\n*** " << Artists.size() << L" row" << (Artists.size() == 1 ? L"" : L"s") << L" returned ***\n";
}


Что я уже пробовал:

Гуглить, сильно пить, долго ходить (в паб и обратно) и, наконец, писать здесь.

OriginalGriff

Голос за честность! :смеяться:

1 Ответов

Рейтинг:
9

Jochen Arndt

Обычно нет необходимости использовать std::wstring с Linux, потому что он использует строки UTF-8 по умолчанию уже много лет. Таким образом, у вас есть полная поддержка Unicode с помощью char строки.

Вы всегда будете сталкиваться с проблемами при использовании std:wstring с Linux, потому что почти все библиотечные функции ожидают char строки.

[ОБНОВЛЕНИЕ]
От Часто задаваемые вопросы · Microsoft / cpprestsdk Wiki · GitHub[^]:

Цитата:
C++ REST SDK использует другой тип строки, зависящий от целевой платформы. Например, для платформы Windows утилита::string_t это std::wstring, которая используется UTF-16, в Linux СТД::строка в кодировке UTF-8.

Так что вы можете использовать utility::string_t вместо этого наберите.
[/ОБНОВЛЕНИЕ]


pkfox

Действительно ( Вы всегда будете сталкиваться с проблемами при использовании std:wstring с Linux)? команда cpprestsdk может похвастаться кросс-платформенной поддержкой - мне нравится разрабатывать с помощью VS в Windows, а затем копировать код в Linux - полагаю, мне просто придется по умолчанию использовать std::string, что не так уж и важно - спасибо за вашу помощь.

Jochen Arndt

Если вы собираетесь передавать такие строки стандартным библиотечным функциям: да.
Вам придется обратить их.

Я видел, что вы используете cpprest, но до сих пор не использовали его. Поэтому я не знал, как он обрабатывает строки внутри себя. Но с интернет-приложениями (HTPP, Jason) строки обычно являются UTF-8. Тогда нет смысла преобразовывать их в широкие символы при синтаксическом анализе и обратно в UTF-8 при выводе.

Я вижу два решения:
Использование зависимого от ОС typedef для строк, используемых вашим приложением, или использование всегда char строк, которые затем должны быть преобразованы из UTF-8 в широкие символы с помощью Windows.

Что здесь лучше, зависит от того, как строки обрабатываются cpprest для Windows и Linux. Быстрый поиск показывает, что cpprest предоставляет необходимые функции преобразования.

И это вызвало вопросы-ответы. Я обновлю свой ответ.

pkfox

Привет Йохан, cpprest имеет эту маленькую жемчужину в basic_types.ч

#ifdef _UTF16_STRINGS
typedef std::wstring string_t;
#еще
определение типа СТД::строка string_t;
#endif
именно это вы и предложили.
Я изменил всю свою wstring на string_t, и все в порядке - спасибо за ваше время