QT C ++ проблема предварительного объявления? - PullRequest
4 голосов
/ 07 июля 2011

Я пытаюсь использовать QTPropertyBrowser для редактирования свойств в моих объектах QObject. Из примера QT Solutions "QtPropertyBrowser" я использую следующие файлы в своем проекте.

http://qt.gitorious.org/qt-solutions/qt-solutions/blobs/master/qtpropertybrowser/examples/object_controller/objectcontroller.cpp

http://qt.gitorious.org/qt-solutions/qt-solutions/blobs/master/qtpropertybrowser/examples/object_controller/objectcontroller.h

Я настраиваю свой CMakeFile следующим образом:

#include_directories("/usr/include")
SET(QTVIEW_SRCS 
  src/main.cpp  
  src/TestWidget.cpp
  src/plugin/IPlugin.cpp
  src/objectcontroller.cpp
)

SET(QTVIEW_MOH_HDRS
 src/TestWidget.h
 src/plugin/IPlugin.h
 src/objectcontroller.h

)

Когда я компилирую файлы как они есть, компилятор выдает ошибку следующим образом -

C: \ SVN \ osaka3d \ ствол \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: В функции-члене 'Virtual Int ObjectController :: qt_metacall (QMetaObject :: Вызов, int, void **) ': C: \ SVN \ osaka3d \ ствол \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: 73: ошибка: неверное использование неполного типа struct ObjectControllerPrivate C: \ SVN \ osaka3d \ ствол \ osaka3d \ QTView \ SRC / objectcontroller.h: 45: ошибка: предварительное объявление структуры ObjectControllerPrivate» C: \ SVN \ osaka3d \ ствол \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: 73: ошибка: ожидаемый спецификатор типа перед 'QtProperty' C: \ SVN \ osaka3d \ ствол \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: 73: ошибка: ожидается ">" раньше 'QtProperty' C: \ SVN \ osaka3d \ ствол \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: 73: ошибка: ожидается '(' до 'QtProperty' C: \ SVN \ osaka3d \ ствол \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: 73: ошибка: 'QtProperty' не был объявлен в этом объеме C: \ SVN \ osaka3d \ ствол \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: 73: ошибка: ожидаемое первичное выражение до ')' токен mingw32-make 2 : * [CMakeFiles / qtview.dir / SRC / moc_objectcontroller.cxx.obj] Ошибка 1 mingw32-make 1 : [CMakeFiles / qtview.dir / all] Ошибка 2 mingw32-make: ** [все] Ошибка 2

Но когда я закомментирую строку:

Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QVariant &))

в "objectcontroller.h"

и закомментируйте строку:

#include "moc_objectcontroller.cxx"

и конец файла "objectcontroller.cpp", он хорошо компилируется, но я не могу использовать SIGNALS / SLOTs для отражения редактирования параметров QObject.

Есть советы?

Ответы [ 2 ]

6 голосов
/ 17 мая 2013

Я столкнулся с той же проблемой (я новичок в qt, но у меня это сработало). Для других людей, ищущих решение, я нашел это:

Что происходит

Проблема в том, что из-за макроса Q_PRIVATE_SLOT сгенерированный moc_XXX.cxx нуждается в полном объявлении класса XXXPrivate для вызова функции закрытого слота. Так как открытый заголовок только пересылает его, форвард cxx не может быть скомпилирован сам по себе. Парни QtPropertyBrowser обошли эту проблему, включив сгенерированный moc_XXX.cpp (обратите внимание на 'pp', cmake генерирует 'xx')) в свой исходный файл (уродливо, но работает). Я также не знаю другого способа сказать moc включить (в данном случае даже не присутствовать) private XXX_p.hpp. Так что давайте придерживаться этого пути.

Затем я удалил сгенерированные файлы moc_XXX.cxx из исполняемого файла, но это привело к тому, что moc никогда не вызывалось. Это случилось, хотя я использовал QT4_WRAP_CPP. Так что после дальнейших поисков я обнаружил ...

Одно дополнение к этому особому случаю: декларация QtProperty отсутствует. Либо добавьте следующую предварительную декларацию или соответствующий файл включения:

#if QT_VERSION >= 0x040400
QT_BEGIN_NAMESPACE
#endif

class QtProperty;

#if QT_VERSION >= 0x040400
QT_END_NAMESPACE
#endif

Решение

Полный кредит предоставляется fullmetalcoder , который представил эту функцию cmake:

function(qt4_wrap_hdrs _moc_srcs)
  qt4_get_moc_flags(_moc_incs)
  set(_mocs)
  foreach(_current_file ${ARGN})
    get_filename_component(_abs_file ${_current_file} ABSOLUTE)
    if(EXISTS ${_abs_file})
      file(READ ${_abs_file} _contents)
      get_filename_component(_basename ${_abs_file} NAME_WE)
      string(REGEX MATCH "Q_OBJECT" _match "${_contents}")
      if(_match)
        set(_moc "${CMAKE_CURRENT_BINARY_DIR}/moc_${_basename}.cpp")
        qt4_create_moc_command(${_abs_file} ${_moc} "${_moc_incs}" "")
        macro_add_file_dependencies(${_abs_file} ${_moc})
        list(APPEND _mocs ${_moc})
      endif(_match)
    endif(EXISTS ${_abs_file})
  endforeach (_current_file)
  set(${_moc_srcs} ${_mocs} PARENT_SCOPE)
endfunction(qt4_wrap_hdrs)

(из http://www.qtcentre.org/threads/37428-using-QT-unit-testing-with-CMake)

Вы можете использовать эту функцию в качестве замены для QT4_WRAP_CPP. Теперь вам нужно только добавить следующую строку в ваш CMakeLists.txt, чтобы компилятор нашел сгенерированные файлы moc_XXX.cpp (новая функция создала файл 'pp' ...):

include_directories(${CMAKE_BINARY_DIR})

Эта функция постоянно вызывает moc и ведет себя больше как в случае qmake . За исключением, конечно, что вы можете легко сделать из исходных сборок.

Но есть одно предупреждение: все moc_XXX.cpp файлы генерируются в CMAKE_BINARY_DIR. Так что если у вас есть два файла include1/foo.hpp и include2/foo.hpp, один будет перезаписан!

1 голос
/ 28 июля 2011

Вы читали следующую статью об использовании Qt и CMake вместе?

http://developer.qt.nokia.com/quarterly/view/using_cmake_to_build_qt_projects

Может быть, вы что-то забыли, например, позвонили QT4_WRAP_CPP в свой CMakeLists.txt.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...