0

在我的项目中,我需要使用宏创建 QObject 派生类(使用 Q_OBJECT 和信号)。该宏位于一个单独的文件中。这是一个简化的示例:

宏在文件 CreateQtClass.h 中声明:

#ifndef __CREATEQTCLASS_H__
#define __CREATEQTCLASS_H__

#define CREATE_QT_CLASS( ClassName ) \
class ClassName : public QObject \
{ \
  Q_OBJECT \
\
 signals: \
  Q_SIGNAL void mySignal( void ); \
}; 

#endif //__CREATEQTCLASS_H__

我使用宏在文件 MyQtClass.h 中创建我的类

#ifndef __MYQTCLASS_H__
#define __MYQTCLASS_H__

#include <QObject>
#include "CreateQtClass.h"

CREATE_QT_CLASS( MyQtClass );

#endif //__MYQTCLASS_H__

在我的 .qbs 文件中,我将 MyQtClass.h 添加到 files 属性,如下所示:

import qbs

QtApplication {
    name: "HelloWorld-Qt"
    files: [ "main.cpp", "MyQtClass.h" ]
}

现在,当运行时qbs build,qbs 不会在 MyQtClass.h 上运行“moc”。看起来它没有正确进行扫描,也没有检测到宏内的 Q_OBJECT。

(我可能会注意到,如果宏声明和使用在同一个文件中,一切正常)。

我的问题:

有没有办法让用户手动强制 qbs 在文件上运行“moc”?

也许我们需要类似“force_moc”文件标签(与“unmocable”相反)之类的东西,我可以将其应用于包含 MyQtClass.h 的组。

添加:

我添加了一个简单的 Makefile 和 main.cpp 来证明 moc 可以很好地与上述方法配合使用:

文件 main.cpp:

#include <QDebug>
#include "MyQtClass.h"

static void mySlot( void )
{
  qDebug() << "Hello slot";
}

int main( void )
{
  MyQtClass c;
  QObject::connect( &c, &MyQtClass::mySignal, &mySlot );
  emit c.mySignal();
  return 0;
}

生成文件:

CXX = /usr/bin/g++
MOC = /home/user/programs/Qt5.11.2/5.11.2/gcc_64/bin/moc

INCLUDES = \
    -I/home/user/programs/Qt5.11.2/5.11.2/gcc_64/include \
    -I/home/user/programs/Qt5.11.2/5.11.2/gcc_64/include/QtCore \
    -I/home/user/programs/Qt5.11.2/5.11.2/gcc_64/mkspecs/linux-g++ \
    -I/usr/include

LINK_FLAGS = \
    -Wl,-m,elf_x86_64,-rpath,/home/user/programs/Qt5.11.2/5.11.2/gcc_64/lib \
    -L/home/user/programs/Qt5.11.2/5.11.2/gcc_64/lib \
    -m64 /home/user/programs/Qt5.11.2/5.11.2/gcc_64/lib/libQt5Core.so.5.11.2 \
    -lpthread

C_FLAGS = \
    -g \
    -O0 \
    -Wall \
    -Wextra \
    -m64 \
    -pipe \
    -fexceptions \
    -fvisibility=default \
    -fPIC \
    -DQT_CORE_LIB \
    $(INCLUDES) \
    -std=c++11

SOURCES = main.cpp
OBJS = $(SOURCES:%.cpp=%.cpp.o)

HEADERS_THAT_NEED_MOC = MyQtClass.h
MOC_OBJS = $(HEADERS_THAT_NEED_MOC:%.h=moc_%.cpp.o)

all: HelloWorld-Qt

HelloWorld-Qt: $(OBJS) $(MOC_OBJS)
    $(CXX) $^ $(LINK_FLAGS) -o $@

%.cpp.o : %.cpp
    $(CXX) $(C_FLAGS) -c $^ -o $@

moc_%.cpp: %.h
    $(MOC) -DQT_CORE_LIB $(INCLUDES) $^ -o $@

clean:
    rm -f *.cpp.o HelloWorld-Qt moc_*.cpp
4

1 回答 1

0

我认为您的方法行不通,与您使用的构建工具无关。请记住, moc 会查找 Q_OBJECT 宏。在 MyQtClass.h 中永远找不到这样的宏,因为 moc 和支持它的构建工具都不会扩展 CREATE_QT_CLASS 宏,因为宏扩展也会扩展 Q_OBJECT。请注意,如果您将 CreateQtClass.h 添加到您的 qbs 文件中,您会注意到 qbs 确实运行 moc -- 但在 CreateQtClass 文件上。这是正确的行为,因为这是 Q_OBJECT 宏发生的地方。我仔细检查了 qmake 和 cmake,它们的行为方式都相同:如果您没有在项目文件中列出 CreateQtClass,它们将不会运行 moc。如果您确实列出了它,则 moc 会在该文件上运行。如果你想继续使用你的宏,你必须确保在调用站点引用 Q_OBJECT,例如 作为宏参数。但即便如此,我也不确定 moc 本身是否会喜欢这种结构。

于 2018-11-07T10:40:34.397 回答