QT C ++ forward declaration problem?

I am trying to use QTPropertyBrowser to edit properties in my QObjects. From the QT Solutions "QtPropertyBrowser" example, I use the following files in my project.

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

I configure my CMakeFile as follows:

#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 ) 

When I compile the files as they are, the compiler gives an error as follows -

C: \ SVN \ osaka3d \ trunk \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: In the member function 'virtual int ObjectController :: qt_metacall (QMetaObject :: Call, int, void **)': C: \ SVN \ osaka3d \ trunk \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: 73: error: invalid use of the incomplete type 'struct ObjectControllerPrivate' C: \ SVN \ osaka3d \ trunk \ osaka3d \ QTView \ SRC / objectcontroller.h: 45: error: forward declaration 'struct ObjectControllerPrivate "C: \ SVN \ osaka3d \ trunk \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: 73: Error: expected type specifier before' QtProperty 'C: \ SVN \ osaka3d \ trunk \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: 73: error: expected '>' to 'QtProperty' C: \ SVN \ osaka3d \ trunk \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: 73: error: expected '(' before 'QtProperty' C: \ SVN \ osaka3d \ trunk \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: 73: Error: "QtProperty" was not declared in this area C: \ SVN \ osaka3d \ trunk \ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: 73: error: expected primary expression before ')' token mingw32-make 2 : * [CMakeFiles /qtview.dir/SRC/moc_objectcontroller.cxx.obj] Error 1 mingw32-make 1 : [CMakeFiles / qtview.dir / all] Error 2 mingw32-make: ** [all] Error 2

But when I comment the line:

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

in "objectcontroller.h"

and comment out the line:

 #include "moc_objectcontroller.cxx" 

and the end of the file "objectcontroller.cpp", it compiles well. But I can not use SIGNALS / SLOT to reflect the editing of QObject parameters.

Any tips?

+4
source share
2 answers

I ran into the same problem (I'm new to qt, but this worked for me). For other people looking for a solution, I found this:

What's happening

The problem is that because of the Q_PRIVATE_SLOT macro, the generated moc_XXX.cxx requires a full declaration of the XXXPrivate class to call the private slot function. Since the public header only forward declares it, the generated cxx cannot be compiled on its own. The QtPropertyBrowser guys circumvented this problem by including the generated moc_XXX.cpp (mind "pp", cmake generates "xx") in the source file (ugly, but it works). I also don't know any other way to tell moc to enable (in this case not even be present) private XXX_p.hpp . So let's stick to this path.

What I did next was to remove the generated moc_XXX.cxx files from the executable, but this caused moc to never be called. This happened, although I used QT4_WRAP_CPP . Therefore, after further searching, I discovered ...

One addition to this special occasion: the QtProperty declaration QtProperty missing. Add either the following forward declaration or the appropriate include file:

 #if QT_VERSION >= 0x040400 QT_BEGIN_NAMESPACE #endif class QtProperty; #if QT_VERSION >= 0x040400 QT_END_NAMESPACE #endif 

Decision

Full credit goes to fullmetalcoder, which introduced this cmake feature:

 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) 

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

You can use this function as a replacement for QT4_WRAP_CPP . Now you need to add the following line to your CMakeLists.txt so that the compiler detects the generated moc_XXX.cpp files (a new function created the file "pp" ...):

 include_directories(${CMAKE_BINARY_DIR}) 

This function calls moc all the time and behaves as in the case of qmake. In addition to what you can easily do from the original builds.

But there is one caveat: all moc_XXX.cpp files moc_XXX.cpp generated in CMAKE_BINARY_DIR . So if you have two files include1/foo.hpp and include2/foo.hpp , then they will be overwritten!

+6
source

Have you read the following article about using Qt and CMake together?

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

Perhaps you are forgetting something, for example, call QT4_WRAP_CPP on your CMakeLists.txt.

+1
source

All Articles