Преобразование wstring в jstring в Linux

У меня проблемы с преобразованием wstring в jstring в unix, так как размер wchar_t в linux составляет 4 байта (а не 2 байта, как в windows, и поэтому я не могу использовать приведение wchar_t к jchar).

Может ли кто-нибудь помочь мне с этим?

Спасибо, Реза


person RezaPlusPlus    schedule 25.11.2011    source источник


Ответы (1)


Вы должны использовать что-то вроде iconv(), потому что широкие строки C++ имеют непрозрачную (читай: неизвестную) кодировку, а Java ожидает UTF16. Попробуй это:

#include <iconv.h>
#include <string>
#include <vector>
#include <iostream>

std::u16string convert(std::wstring s)
{
  iconv_t cd = iconv_open("UTF-16BE", "WCHAR_T");

  if (cd == iconv_t(-1))
  {
    std::cout << "Error while initializing iconv: " << errno << std::endl;
    iconv_close(cd);
    return std::u16string();
  }

  std::size_t n = s.length() * 2 + 1; // Each character might use up to two CUs.
  const std::size_t norig = n;
  std::size_t m = s.length() * sizeof(std::wstring::value_type);

  std::vector<char16_t> obuf(n);
  char * outbuf = reinterpret_cast<char*>(obuf.data());
  const char * inbuf = reinterpret_cast<const char*>(&s[0]);

  const std::size_t ir = iconv(cd, const_cast<char**>(&inbuf), &m, &outbuf, &n);

  if (ir == std::size_t(-1))
  {
    std::cout << "Error while converting with iconv(): " << errno << ":" << EINVAL << ", left " << m
              << ", written " << std::dec << norig - n << " bytes." << std::endl;
    iconv_close(cd);
    return std::u16string();
  }

  iconv_close(cd);

  return std::u16string(obuf.data(), (norig - n)/sizeof(std::u16string::value_type));
}

Если у вас нет char16_t и std::u16string, вы можете использовать uint16_t в качестве основного типа символов и std::basic_string<uint16_t> или std::vector<uint16_t> в качестве результирующего контейнера.

person Kerrek SB    schedule 25.11.2011
comment
Спасибо. Итак, этот метод преобразует строку wstring в строку utf16, верно? Тогда как мне создать jstring из этой wstring? - person RezaPlusPlus; 25.11.2011
comment
@RezaPlusPlus: input — это непрозрачная широкая строка C++, а output этой функции — это четко определенная строка UTF-16BE. Я не знаю, что такое jstrings, но вы должны иметь возможность так или иначе передавать указатель на первый элемент результата в jstring. - person Kerrek SB; 25.11.2011
comment
Кстати, является ли std::u16string стандартным STL? - person RezaPlusPlus; 25.11.2011
comment
@RezaPlusPlus: стандартного STL не существует; STL — это исторический артефакт 1994 года :-) u16string является частью стандарта C++11. Если у вас нет поддержки для этого, вы можете вместо этого использовать вектор uint16_ts, как я предлагаю в последнем абзаце. - person Kerrek SB; 25.11.2011
comment
Спасибо и извините, что пропустил последний абзац. - person RezaPlusPlus; 25.11.2011