Записки программиста Программирование и не только

17Авг/160

QBitArray to QByteArray

QByteArray bit2byte(const QBitArray &__bits)
{
    // 
    QByteArray bytes;
    bytes.resize(__bits.count() / 8 + 1);    // Резервируем место
    bytes.fill(0);                           // Заполняем всё нулями

    // Конвертируем из QBitArray в QByteArray
    for(int b = 0; b < __bits.count(); ++b)
    {
        bytes[b/8] = (bytes.at(b/8) | ( (__bits.testBit(b) ? 1 : 0)<<(7-(b%8)) ) );
        // Конструкция (7-(b%8)) даёт прямой порядок. Для обратного (b%8)
    }

    return bytes;
}

Ключевые слова:
qbitarray2qbytearray

Метки записи: , , Нет комментариев
22Янв/130

Для чего нужен union

Продолжаю открывать для себя С++...

Объединение служит для, как бы это ни казалось странным, объединения.
Это позволяет, записывая данные в одно поле union'а, одновременно получать эти же данные в другом поле. Причем поля могут быть разные по содержимому.

Пример:

typedef struct
{
  unsigned short fbNVRIncorrectCRC    :1;
  unsigned short fbConfigIncorrectCRC :1;
  unsigned short fbSPIInterfaceError  :1;
  unsigned short fbMFIncorrectCRC     :1;
  unsigned short fbMFWriteError       :1;
  unsigned short fbMFNotInstalled     :1;
  unsigned short fbEEJFatalError      :1;
  unsigned short fbUnused1            :1;

  unsigned short fbNotInitialized     :1;
  unsigned short fbNonFiscalMode      :1;
  unsigned short fbShiftOpened        :1;
  unsigned short fb24HourOverflow     :1;
  unsigned short fbEEJArchieveClosed  :1;
  unsigned short fbEEJNotActivated    :1;
  unsigned short fbMFNoMemoryForShift :1;
  unsigned short fbMFWrongPassword    :1;

  unsigned char dbDocumentType;
} ST_FRSTATUS;

typedef union
{
  ST_FRSTATUS stStatus;
  unsigned char dbStatus[3];
} UN_FRSTATUS;

И теперь можно записать данные в массив unsigned char dbStatus[3]; и потом получить их из структуры уже разобранными.

Т.е. можно обратиться к dbStatus[2] и к stStatus.dbDocumentType и получить один и тот же результат.
Единственное - нельзя обращаться по разным именам в одном блоке программы..

21Янв/130

Вынести определение массива структур в другой файл

В продолжении к красоте

Объявляем (declaration)

//st.h
enum {
    /* I/O ERRORS */
    ERR_INVALID_STATUS = 0x01,
    ERR_INVALID_FUNCTION = 0x02
};

struct fr_errs_struct
{
	int err;
	const char * const msg;
};

extern struct fr_errs_struct fr_errs [];

Определяем (definition)

//st.cpp
#include <st.h>

struct fr_errs_struct fr_errs [] = {
    {ERR_INVALID_STATUS,        "Функция невыполнима при данном статусе"},
    {ERR_INVALID_FUNCTION,      "В команде указан неверный номер функции"},
    {0,     ""}
};

Ну и функция для использования всего этого

const char* getText(int aErr)
{
    int i = 0;
    while(fr_errs[i].err && fr_errs[i].err != aErr)
    {
        i++;
    }
    return fr_errs[i].msg;
}
Метки записи: , Нет комментариев
18Янв/130

Красота:

 enum {
	/* I/O ERRORS */
	ERR_INVALID_STATUS = 0x01,
	ERR_INVALID_FUNCTION = 0x02
};

struct
{
	int err;
	const char * const msg;
} fr_errs [] = {
	{ERR_INVALID_STATUS,		"Функция невыполнима при данном статусе"},
	{ERR_INVALID_FUNCTION,		"В команде указан неверный номер функции"}
	{0,		""}
}; 
Метки записи: Нет комментариев
26Ноя/121

[Qt] UTF в 1251 и 1251 в UTF

На входе имеем строку в HEX виде, да еще и в кодировке CP-1251. Надо Переделать её в UTF-8
Я использовал для этого QTextCodec.

QByteArray msg = QByteArray::fromHex("cde5eff0e0e2e8ebfcedeee520f1eeeee1f9e5ede8e5204b4f4e5f544d5f484f53544b4e4620eef220d3cad2d121");
QTextCodec *codec = QTextCodec::codecForName("Windows-1251");
QString strf = codec->toUnicode(msg);
qDebug() << strf;

Переварили строчку и надо отправить её обратно, но на выходе нужен CP-1251
Процедура обратная.

QByteArray wtf_s(strf.toStdString().c_str()); //либо так
//wtf_s.append(strf); //либо так

QByteArray wtf = codec->fromUnicode(wtf_s);
qDebug() << wtf.toHex();

Ключевые слова: Qt, UTFtoCP1251, CP1251toUTF

25Июл/125

[Android NDK] Unable to find native library

Пытаясь собрать пример из NDK получаю вот такую ошибку:

Caused by: java.lang.IllegalArgumentException: Unable to find native library: native-activity

Весь интернет пишет какую-то ересь типа:
"Поправьте в AndroidManifest.xml строчку android:hasCode="false" на android:hasCode="true" и будет вам счастье"

А вот хер! Никакого эффекта.
Так бы и закончилось моё желание писать на С++ под Дроида, но тут я натыкаюсь на отличную ссылочку:
http://mobilepearls.com/labs/ndk-builder-in-eclipse/

Получается, что проблема в самом Эклипсе, блин.

Коротко:

1. Заходим в Properties проекта в раздел Builders. Жмём New...
2. Выбираем тип Program и жмём Ok
3. Location указываем путь до ndk-builer'а (я указал абсолютный путь. Под Вин это звучит так: <путь в системе>\android-ndk-r8\ndk-build.cmd)
4. Working directory - путь до папки с проектом (Моё: <путь в системе>\android-ndk-r8\samples\native-activity
5. На том же окошке переходим во вкладку Refresh, ставим галочку и выбираем Specific resources. Разворачиваем проект и ставим галочку на lib. Finish
6. Вкладка Build Options. Проверяем наличие галочки на During auto builds и ставим галку на Specify working set of relevant resources. Разворачиваем проект и ставим галочку на jni
7. Жмем Apply, Ok, Ok

Не забываем нажать Project/Clean
Всё, теперь проект запускается без ошибок.

Метки записи: , , 5 Комментарии
5Июн/120

[Qt] Запись файла в SQLite

Собственно, всё просто
Создали в БД таблицу с атрибутом типа BLOB:

CREATE TABLE fileTable (id_file integer NOT NULL PRIMARY KEY AUTOINCREMENT, file BLOB NOT NULL);

Потом:

    QFile file(QApplication::applicationDirPath().append("/file"));
    file.open(QIODevice::ReadOnly);    //открыли файл
    QByteArray ba = file.readAll();    //прочитали из него всё
    QSqlQuery query(QSqlDatabase::database("sql"));    //
    query.prepare("INSERT INTO fileTable (file) VALUES(:val);");    //создали запрос
    query.bindValue ( ":val", ba);
    query.exec();    //запустили
    file.close();    //файл закрыли

И всё. Ну, естественно, дописали обработку ошибок.

Обратный процесс - чтение файла из SQLite:

    QFile file(QApplication::applicationDirPath().append("/newfile"));
    file.open(QIODevice::WriteOnly);
    QSqlQuery query(QSqlDatabase::database("sql"));

    query.prepare("SELECT file FROM fileTable;");
    query.exec();

    query.next();
    QByteArray ba = query.value(0).toByteArray();
    file.write(ba);
    file.close();
Метки записи: , , , Нет комментариев
28Апр/120

qDebug() и структуры

В дополнении к этому

Есть в классе произвольная структура.
Надо научить её выводиться в qDebug()

Структура:

class MyClass
{
    struct MyStruct
    {
        quint8 a1;
        quint8 a2;
        quint8 a3;
        quint8 a4;
    };
};

Дописываем в *.h :

#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug, const MyClass::MyStruct);
#endif

А в *.cpp :

QDebug operator<<(QDebug aDbg, const MyClass::MyStruct strc)
{
    aDbg.nospace() << "( " << "MyStruct" << " ("
                   << strc.a1 << ", "
                   << strc.a2 << ", "
                   << strc.a3 << ", "
                   << strc.a4
                   << ") )";
    return aDbg.space();
}
Метки записи: , , Нет комментариев
20Апр/120

[QtScript] Получить доступ из пользовательской функции к интерфейсу.

Продолжаем извращаться.

Захотелось мне написать свою функцию print для QtScript чтобы вывод шел в QTextEdit.
Класс, который содержит в себе TextEdit у меня зовётся Widget

Функция (Вне классов):

QScriptValue funcPrint(QScriptContext *context, QScriptEngine *engine)
{
    QString result;
    for (int i = 0; i < context->argumentCount(); ++i) {
        if (i > 0)
            result.append(" ");
        result.append(context->argument(i).toString());
    }

    Widget *bgg = (Widget*)engine->parent();
    bgg->print(result);

    return engine->undefinedValue();
}

Регистрируем:

engine->globalObject().setProperty("print", engine->newFunction(funcPrint, 1));

Метод банален:

void Widget::print(QString aStr)
{
    ui->TextEdit->append(aStr);
}

Тонкости:
engine является членом класса Widget (приватным) и инициализируется:

engine = new QScriptEngine(this);

Обязательно указать родителя! Иначе его потом не получить и будет segfault

Соответственно можно объявить engine и не указателем.
Тогда обязательно(!) инициализировать в конструкторе:

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget),
    engine(this)              //!!!!!
{
    ui->setupUi(this);
    ...
}
Метки записи: , , Нет комментариев
20Мар/120

[Еще вариант] Отправляем объект из внешней библиотеки в скрипт.

В первом варианте код был жестко завязан на интерфейсный класс плагина.

Как оказалось, можно обойтись и без него.
Для этого надо:
1. В плагине к конструктору добавить служебную конструкцию Q_INVOKABLE. Т.е. должно получиться так:

Q_INVOKABLE explicit ScriptObject(QObject *parent = 0);

А в основной программе нужно убрать строку с приведением qobject_cast и заменить строку с регистрацией объекта в движке на вот такую:

QScriptValue scObj = engine.newQObject(plugin->metaObject()->newInstance(), QScriptEngine::ScriptOwnership);

И всё! Никакой привязки к интерфейсу!

Теперь буду разбираться с тем, как бы всё это безобразие соединять сигналами. Как-нибудь по динамичнее.

upd: Не забываем в после засовывания объекта в скрипт его там зарегистрировать.

engine.globalObject().setProperty("ScObj", scObj);
Метки записи: , , Нет комментариев