Расширение макроса в МОК
-
29-09-2019 - |
Вопрос
Я хотел бы сохранить информацию о классе с помощью макроса Q_CLASSINFO. Однако я хотел бы обернуть его в свой собственный макрос, например:
#define DB_TABLE( TABLE ) \
Q_CLASSINFO( "db_table", #TABLE )
#define DB_FIELD( PROPERTY, COLUMN ) \
Q_CLASSINFO( "dbcol_" #PROPERTY, #COLUMN )
class Foo : public QObject
{
Q_OBJECT
DB_TABLE( some_table )
DB_FIELD( clientName, client_name )
}
К сожалению, MOC не расширяет макросы, поэтому Q_Classinfo не добавляется.
Я пытался прокормить MOC с уже предварительно назначенным источником, но не удается в некоторых классах QT.
Вы знаете любой обходной путь для этого?
Решение
Помимо прокатки своего препроцессора Pre-Moc, нет. Это то, что делает Meego Touch, например. С самих Nokia это делают, я считаю, что нет другого пути.
В вашем случае, только привлечет только перевод ваших собственных деклараций в Q_CLASSINFO, поэтому он не должен быть слишком сложным. Если вы используете QMake, он также может быть добавлен в последовательность сборки.
Другие советы
Простой способ сделать это модифицирующий препроцессор MOC.
- Перейти к исходным коде QT для qtbase / src / tools / moc Например, (C: Qt qt5.0.1 5.0.1 src qtbase src tools moc)
- Создайте новую копию проекта MOC, например, MOC_Modified
- Откройте копию проекта MOC с QTCREATOR (файл MOC.PRO)
- Откройте файл PreProcessor.cpp и перейдите к Символы Препроцессор :: Препроцессированные (const Qbytearray & filename, qiodevice * file) функция
Поиск по линии:
// phase 1: get rid of backslash-newlines input = cleaned(input); // <- insert your code to modify input variable // input is a QByteArray object that contents the source code of .h file than moc is processing // I had created the replaceCustomMacros function, see next line replaceCustomMacros(input); ...
Составьте новый исходный код. Исполняемый файл MOC сгенерирован в папку / Bin (если вы используете Windows Some на C: /bin/moc.exe)
Перейдите в BIN (C: QT QT5.0.1 5.0.1 qt qt5.0.1 5.0.1 qt qt5.0.1 5.0.1 qt qt5.0.1 5.0.1 qt qt5.0.1 5.0.1 msvc2010 bin) и переименовать файл исполняемого moc, например, moc.exe.bak
Скопируйте новый исполняемый файл MOC в папку Qt Bin.
В вашем нынешнем приложении вам необходимо создать макрос, например:
#ifndef Q_MOC_RUN #define DB_FIELD( PROPERTY, COLUMN ) #endif //or in my case #ifndef Q_MOC_RUN #define Q_SERVICE_INFO(method, path, type) #endif
Наконец я позволил вам собственный исходный код функции ReplaceCustommaCros:
Эта функция преобразует Q_service_info (метод, путь, тип) макрос к Q_ClassInfo («SRV: // Метод», «Тип: Путь»)
void Preprocessor::replaceCustomMacros(QByteArray &source)
{
QString str(QLatin1String(source.data()));
QString param_exp(QLatin1String("([^,\n]+)"));
QByteArray expression("Q_SERVICE_INFO\\s*\\(");
expression
.append(param_exp.toLatin1())
.append(",")
.append(param_exp.toLatin1())
.append("(,")
.append(param_exp.toLatin1())
.append(")?\\)");
QRegExp *reg_ex = new QRegExp(QLatin1String(expression));
int pos = -1, offset = -1, len = str.length();
while ((offset = reg_ex->lastIndexIn(str, pos)) != -1)
{
reg_ex->cap(1);
pos = -(len - offset) - 1;
QString capturedString = reg_ex->capturedTexts().at(0);
QString pattern = capturedString;
pattern.remove(0, pattern.indexOf(QLatin1String("(")) + 1);
pattern.remove(pattern.length() - 1, 1);
QStringList params = pattern.split(QLatin1String(","));
QString method = params.at(0).trimmed();
method = method.mid(1, method.length() - 2);
QString type;
if (params.length() < 3)
{
type.append(QLatin1String("GET"));
}
else
{
type = params.at(2).trimmed();
type = type.mid(1, type.length() - 2);
}
QString path = params.at(1).trimmed();
path = path.mid(1, path.length() - 2);
source.replace(offset, capturedString.length(), QString(QLatin1String("Q_CLASSINFO(\"srv://%1\",\"%2:%3\")")).arg(method, type, path).toLatin1());
}
delete reg_ex;
}
Я не нашел никакого конкретного решения в Интернете, то я опубликовал это решение.
Удачи :)