LINUX.ORG.RU

Qt и кодировки

 , , opos,


0

3

Работаю с COM-объектом через qaxobject.
COM-объект это OPOS драйвер для ККМ (просто для справки).
Вот так вызвываю метод:

printer->PrintRecItem(QString::fromUtf8("123 тест test"), ...);

Вот сам метод:

inline int IOPOSFiscalPrinter::PrintRecItem(const QString& Description, qlonglong Price, int Quantity, int VatInfo, qlonglong UnitPrice, const QString& UnitName)
{
    int qax_result;
    void *_a[] = {(void*)&qax_result, (void*)&Description, (void*)&Price, (void*)&Quantity, (void*)&VatInfo, (void*)&UnitPrice, (void*)&UnitName};
    qt_metacall(QMetaObject::InvokeMetaMethod, 43, _a);
    return qax_result;
}

В результате получается такая строка:

123 ?xe? test

Уже голову сломал, пытаясь определить, какую необходимо передать кодировку. По идее, драйвер поддерживает UTF-8, но, судя по результату, что-то где-то ломается.

★★

Последнее исправление: SaBo (всего исправлений: 1)

а с чего ты взял что так (void*)&Description ты передаешь UTF-8? Используй toUtf8.

P.S. c-style cast в плюсах - это отвратительно

Torvus
()

Вот сам метод:

Это же результат работы moc (препроцессор Qt)?

Ты лучше покажи, какой реально слот дергается. И еще строка

QString::fromUtf8("123 тест test")

имеет смысл только в qt4. Удостоверься что у тебя сам исходник закодирован в utf8.

staseg ★★★★★
()

Венда? Так так там скорее всего ucs-2 или utf-16. Хотя может и 1251 быть.

Разбирайся, что в com объекте лежит точно. Без этого будешь долго страдать.

invy ★★★★★
()
Последнее исправление: invy (всего исправлений: 1)
Ответ на: комментарий от false

Так Qt5. Нету там больше такого.

SaBo ★★
() автор топика
Ответ на: комментарий от staseg

Это же результат работы moc (препроцессор Qt)?

Да.

Ты лучше покажи, какой реально слот дергается.

В смысле? Это единственный осмысленный код, который я нашёл.

SaBo ★★
() автор топика
Ответ на: комментарий от Torvus

Вот так вот:

const QByteArray desc = Description.toUtf8();
void *_a[] = {(void*)&qax_result, (void*)&desc, (void*)&Price, (void*)&Quantity, (void*)&VatInfo, (void*)&UnitPrice, (void*)&UnitName};

Печатает:

????????t?????
SaBo ★★
() автор топика
Ответ на: комментарий от SaBo

чукча не читатель? доки совсем лень читать? например, вот тут видно, что QByteArray не содержит прямой ссылки на данные. вместо этого используется pimpl. следовательно так (void*)&desc ты получишь не то что ожидаешь. у QByteArray есть метод data. вот его и используй

Torvus
()
Ответ на: комментарий от SaBo

Чувак, тебе сейчас насоветуют. Не модифицируй код PrintRecItem, он автоматически сгенерирован и пакует свои аргументы для передачи через механизм Qt сигнал/слот. Конкретно тебе сейчас предлагают сломать механизм запаковки данных, оставив распаковку прежней.

1. Таки удостоверься, что драйвер поддерживает utf8.

2. QString::fromUtf8 ждет, что ее аргумент будет закодирован в utf8. Проверь, что ты передаешь ему строку в нужной кодировке. В данном случае, что твой исходник закодирован в utf8.

3. Я не знаю, что такое OPOS/KKM, поэтому последний пункт может быть расплывчатым. Куда распечатывается строка на выходе? Если это консоль, переведена ли она в локаль utf8? Если какой-то девайс, не надо ли его как-то настроить на utf8?

staseg ★★★★★
()
Ответ на: комментарий от staseg

KKM - принтер кассовых чеков. Соответственно, на него и идёт печать.
OPOS - спецификация для работы с такими принтерами.
OPOS представляет из себя OLE, а драйвер для работы с принтером его поддерживает, т.е. OPOS - это надстройка над драйвером. Работает как-то так:
Application -> OPOS -> Driver -> Fiscal printer.

Utf8 поддерживает. Есть тестовое приложение, которое использует тот же OPOS и печатает кириллицу, если драйвер принтера перевести в Utf8.

SaBo ★★
() автор топика

попробуй уже toLocal8Bit()?
может, он не поддерживает утф?

и если однобайтная, то может и cp1251...

aol ★★★★★
()
Ответ на: комментарий от SaBo

если драйвер принтера перевести в Utf8

о, а это как? надо же метод какой дёрнуть в апи или настроечку сделать.. в ОП об этом ни слова.

aol ★★★★★
()
Ответ на: комментарий от aol

Этим сам драйвер заведует. Для меня это выглядит как запись в реестре, а как реализовано - хз.

SaBo ★★
() автор топика
Ответ на: комментарий от SaBo

так. стоп. PrintRecItem - это слот? тогда трогать его реализацию бесполезно. мок перегенерит его заново. значит все дело в QString::fromUtf8(«123 тест test»). попробуй так

QString::fromUtf8("123 \u0442\u0435\u0441\u0442 test")

Torvus
()
Ответ на: комментарий от Torvus

так. стоп. PrintRecItem - это слот? тогда трогать его реализацию бесполезно. мок перегенерит его заново.

Мок тут, вроде бы, не причем. Этот файл сгенерирован с помощью dumpcpp.

попробуй так

123 ?xe? test
SaBo ★★
() автор топика

Нашёл ещё вот такой интересный метод. Но результат тот же.

SaBo ★★
() автор топика
Ответ на: комментарий от Torvus
error: 'class QMetaMethod' has no member named 'signature'
SaBo ★★
() автор топика
Ответ на: комментарий от Torvus
printer->metaObject()->method(43).methodSignature()
PrintRecItem(QString,qlonglong,int,int,qlonglong,QString)
SaBo ★★
() автор топика
Ответ на: комментарий от SaBo

Вот код:

printer->PrintRecItem(QString::fromUtf8("test тест 123"), 100 * 100, 0, 0, 0, QString::fromUtf8("ps"));
SaBo ★★
() автор топика
Ответ на: комментарий от SaBo

есть какие-нибудь мысли, почему так?

потому что, емнип, в пятерке многое задепрекейтили, включая setcodecfor* и fromUTF8.

Надо читать статьи, как они теперь рекомендуют жить. Я это пока только по крикам от коллег знаю. Сам на Qt мало пишу.

aol ★★★★★
()
Ответ на: комментарий от SaBo

Собрал с Qt4 (вместо Qt5) и всё магическим образом заработало.

Мде. Шёл третий (!) год с момента выпуска Qt 5.0.0; куча багов так и не была исправлена.

EXL ★★★★★
()
Ответ на: комментарий от SaBo

Опять всё сломалось. Теперь и с Qt4 ерунду печатает.

SaBo ★★
() автор топика

Короче говоря, ККМ умеет печатать в UTF-8 и OEM 866.
С UTF-8 - это, судя по всем, был косяк драйвера (не подхватывал настройки). Как конвертировать QString из utf-8 в OEM 866 см. тут.

SaBo ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.