woboq / verdigris

Qt without moc: set of macros to use Qt without needing moc
https://woboq.com/blog/verdigris-qt-without-moc.html
GNU Lesser General Public License v3.0
638 stars 58 forks source link

What if declaration and implementation is in the same header? #98

Closed ghost closed 1 year ago

ghost commented 1 year ago

It seems you have not yet considered such usage? From README.md, it seems you required to have a clear distinction between declarations (header) and implementations (source file) with two separate W_OBJECT and W_OBJECT_IMPL macros.

Have a look at this: https://github.com/fpc/Lazarus/tree/main/lcl/interfaces/qt5/cbindings

This particular example (many like this on that source tree):

https://github.com/fpc/Lazarus/blob/main/lcl/interfaces/qt5/cbindings/src/qabstractbutton_hook.h

There is no qabstractbutton_hook.cpp, everything was done solely on that header.

How to use Verdigris with it? Don't tell me I had to refactor the code to follow your discipline. I know it's bad practice to have declarations and implementations on the same header file (with the exception of templates). But it's someone else's code not me, I can't do that (it took too much effort to do such a refactoring). I want to have my source tree less divergent from upstream (above project) as much as possible.

I have spent hours to convert it from Qt's slots syntax to Verdigris's W_SLOT macro. I don't want my effort to be useless!

CopperSpice at least have a tool to automate this process (PepperMill) even though it's currently broken. With Verdigris, I have to do everything manually. CopperSpice doesn't have two macros like W_OBJECT and W_OBJECT_IMPL, only CS_OBJECT. Maybe I should wait for them to fix PepperMill and continue with CopperSpice rather than trying with Verdigris in vain like that :facepalm:

arBmind commented 1 year ago

W_OBJECT_IMPL_INLINE is intended for your use case.

arBmind commented 1 year ago

You also have the qabstractbutton_hook_c.cpp. The W_OBJECT_IMPL macro can be placed in any cpp file where the QObject is known. You have to avoid using it twice.

Benefit compared to the INLINE macros is the compile speed, as it has to be parsed parsed only once.

ghost commented 1 year ago

W_OBJECT_IMPL_INLINE is intended for your use case.

Please update README.md, this Correspondance Table is incomplete.

ghost commented 1 year ago

@arBmind Do you have Qt5 installed on your machine? Have a look at this: https://github.com/iahung/qt5pas

Templates is impossible to debug. A bunch of gibberish printed on the screen. I tried my best to read and I think it's your code's bug not me.

arBmind commented 1 year ago

It seems your bindings use Qt 5.6.1. From Verdigris Readme.md "Tested with Qt >= 5.9". I guess this might not work well here.

Sorry, I cannot solve your problems. Verdigris works when used correctly. If you have concrete issues feel free to bring them up here. But we cannot fix the problem of everyone for free here, this is beyond the scope of this project.

ghost commented 1 year ago

It seems your bindings use Qt 5.6.1. From Verdigris Readme.md "Tested with Qt >= 5.9". I guess this might not work well here.

Sorry, I cannot solve your problems. Verdigris works when used correctly. If you have concrete issues feel free to bring them up here. But we cannot fix the problem of everyone for free here, this is beyond the scope of this project.

It builds fine with latest Qt (with MOC). The error message if you want is:

[204/286] Building CXX object CMakeFiles/Qt5Pas.dir/src/qabstractitemmodel_hook_c.cpp.obj
FAILED: CMakeFiles/Qt5Pas.dir/src/qabstractitemmodel_hook_c.cpp.obj
C:\msys64\mingw64\bin\c++.exe -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_NO_DEBUG -DQT_PRINTSUPPORT_LIB -DQT_WIDGETS_LIB -DQt5Pas_EXPORTS -IC:/msys64/home/iahung/cbindings/verdigris -isystem C:/msys64/mingw64/include/QtWidgets -isystem C:/msys64/mingw64/include/QtGui -isystem C:/msys64/mingw64/include/QtCore -isystem C:/msys64/mingw64/share/qt5/mkspecs/win32-g++ -isystem C:/msys64/mingw64/include/QtNetwork -isystem C:/msys64/mingw64/include/QtPrintSupport -Wfatal-errors -Wno-deprecated-declarations -O3 -std=gnu++14 -MD -MT CMakeFiles/Qt5Pas.dir/src/qabstractitemmodel_hook_c.cpp.obj -MF CMakeFiles\Qt5Pas.dir\src\qabstractitemmodel_hook_c.cpp.obj.d -o CMakeFiles/Qt5Pas.dir/src/qabstractitemmodel_hook_c.cpp.obj -c C:/msys64/home/iahung/cbindings/src/qabstractitemmodel_hook_c.cpp
In file included from C:/msys64/home/iahung/cbindings/src/qabstractitemmodel_hook_c.cpp:11:
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h: In instantiation of 'constexpr void w_internal::handleType(State&, TypeStr, std::enable_if_t<(! MetaTypeIdIsBuiltIn<T>::value)>*) [with T = Qt::Orientation; State = LayoutBuilder; TypeStr = stringFetch<0, 0>(const StringViewArray<>&, std::enable_if_t<true, void>*)::_; std::enable_if_t<(! MetaTypeIdIsBuiltIn<T>::value)> = void]':
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h:541:21:   required from 'constexpr const w_internal::LayoutBuilder w_internal::dataLayout<QAbstractItemModel_hook>'
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h:1072:65:   required from 'static constexpr QMetaObject w_internal::FriendHelper::createMetaObject() [with T = QAbstractItemModel_hook]'
C:/msys64/home/iahung/cbindings/src/qabstractitemmodel_hook_c.cpp:17:1:   required from here
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h:893:53:   in 'constexpr' expansion of 'w_internal::createLayout<QAbstractItemModel_hook>()'
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h:889:24:   in 'constexpr' expansion of 'w_internal::generateDataPass<QAbstractItemModel_hook, LayoutBuilder>(r)'
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h:869:24:   in 'constexpr' expansion of 'w_internal::foldMethods<1073741824, QAbstractItemModel_hook**, MethodParametersGenerator<LayoutBuilder> >(w_internal::MethodParametersGenerator<w_internal::LayoutBuilder>((* & state)))'
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h:118:34:   in 'constexpr' expansion of 'w_internal::foldState<1073741824, SlotStateTag, QAbstractItemModel_hook**, MethodParametersGenerator<LayoutBuilder>&>((* & f))'
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h:111:9:   in 'constexpr' expansion of 'w_internal::fold<FoldState<MethodParametersGenerator<LayoutBuilder>&, SlotStateTag, QAbstractItemModel_hook**>&, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17>((std::make_index_sequence<18>(), std::make_index_sequence<18>()), fs)'
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h:92:15:   in 'constexpr' expansion of '(& f)->w_internal::FoldState<w_internal::MethodParametersGenerator<w_internal::LayoutBuilder>&, w_internal::SlotStateTag, QAbstractItemModel_hook**>::operator()<w_internal::Index<1> >((w_internal::index<1>, const w_internal::Index<1>()))'
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h:106:40:   in 'constexpr' expansion of '(&((w_internal::FoldState<w_internal::MethodParametersGenerator<w_internal::LayoutBuilder>&, w_internal::SlotStateTag, QAbstractItemModel_hook**>*)this)->w_internal::FoldState<w_internal::MethodParametersGenerator<w_internal::LayoutBuilder>&, w_internal::SlotStateTag, QAbstractItemModel_hook**>::f)->w_internal::MethodParametersGenerator<w_internal::LayoutBuilder>::operator()<w_internal::MetaMethodInfo<void (QAbstractItemModel_hook::*)(Qt::Orientation, int, int), 8, std::integral_constant<void (QAbstractItemModel_hook::*)(Qt::Orientation, int, int), &QAbstractItemModel_hook::headerDataChanged_hook>, w_internal::StringViewArray<>, w_internal::StringViewArray<> >, w_internal::Index<1> >(w_state((i, w_internal::Index<1>()), (w_internal::SlotStateTag(), w_internal::SlotStateTag()), 0), (i, w_internal::Index<1>()))'
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h:565:38:   in 'constexpr' expansion of '((w_internal::MethodParametersGenerator<w_internal::LayoutBuilder>*)this)->w_internal::MethodParametersGenerator<w_internal::LayoutBuilder>::generateSingleMethodParameter<w_internal::MetaMethodInfo<void (QAbstractItemModel_hook::*)(Qt::Orientation, int, int), 8, std::integral_constant<void (QAbstractItemModel_hook::*)(Qt::Orientation, int, int), &QAbstractItemModel_hook::headerDataChanged_hook>, w_internal::StringViewArray<>, w_internal::StringViewArray<> >, QAbstractItemModel_hook, void, Qt::Orientation, int, int>(((w_internal::MetaMethodInfo<void (QAbstractItemModel_hook::*)(Qt::Orientation, int, int), 8, std::integral_constant<void (QAbstractItemModel_hook::*)(Qt::Orientation, int, int), &QAbstractItemModel_hook::headerDataChanged_hook>, w_internal::StringViewArray<>, w_internal::StringViewArray<> >::Func)method.w_internal::MetaMethodInfo<void (QAbstractItemModel_hook::*)(Qt::Orientation, int, int), 8, std::integral_constant<void (QAbstractItemModel_hook::*)(Qt::Orientation, int, int), &QAbstractItemModel_hook::headerDataChanged_hook>, w_internal::StringViewArray<>, w_internal::StringViewArray<> >::func), (* & method))'
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h:573:32:   in 'constexpr' expansion of 'w_internal::handleArgTypes<Qt::Orientation, int, int, LayoutBuilder, StringViewArray<>, 0, 1, 2>((* &((w_internal::MethodParametersGenerator<w_internal::LayoutBuilder>*)this)->w_internal::MethodParametersGenerator<w_internal::LayoutBuilder>::s), method.w_internal::MetaMethodInfo<void (QAbstractItemModel_hook::*)(Qt::Orientation, int, int), 8, std::integral_constant<void (QAbstractItemModel_hook::*)(Qt::Orientation, int, int), &QAbstractItemModel_hook::headerDataChanged_hook>, w_internal::StringViewArray<>, w_internal::StringViewArray<> >::paramTypes, (w_internal::MetaMethodInfo<void (QAbstractItemModel_hook::*)(Qt::Orientation, int, int), 8, std::integral_constant<void (QAbstractItemModel_hook::*)(Qt::Orientation, int, int), &QAbstractItemModel_hook::headerDataChanged_hook>, w_internal::StringViewArray<>, w_internal::StringViewArray<> >::argSequence, const std::integer_sequence<unsigned int, 0, 1, 2>()))'
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h:548:33:   in 'constexpr' expansion of 'w_internal::handleArgType<Qt::Orientation, LayoutBuilder, stringFetch<0, 0>(const StringViewArray<>&, std::enable_if_t<true, void>*)::_>((* & ss), w_internal::stringFetch<0, 0>((* & typeNames), 0))'
C:/msys64/home/iahung/cbindings/verdigris/wobjectimpl.h:336:41: error: 'name' is not a member of 'w_internal::W_TypeRegistery<Qt::Orientation>'
  336 |     s.addTypeString(W_TypeRegistery<T>::name);
      |                                         ^~~~
compilation terminated due to -Wfatal-errors.
ninja: build stopped: subcommand failed.

The problematic source is qabstractitemmodel_hook_c.cpp and qabstractitemmodel_hook.h. I know I can't have people fix my problem for free. But from the error message, I think it's your code's problem, not me. Maybe you will think again if you read the error message.

ghost commented 1 year ago

Qt::Orientation is an enum: https://doc.qt.io/qt-5/qt.html#Orientation-enum

You could try to find 'name' on qabstractitemmodel_hook_c.cpp and qabstractitemmodel_hook.h and I'm sure with you there is no 'name' on them. So what does the error about 'name' is not a member of come from? It comes from your code!

arBmind commented 1 year ago

You are already near the bottom of this. You need to use W_REGISTER_ARGTYPE for all argument types of slots and signals. Otherwise C++ has no way to get the type names needed for the MOC data generation.

See: https://github.com/woboq/verdigris/blob/master/tutorial/tutorial.cpp#L281

ghost commented 1 year ago

You are already near the bottom of this. You need to use W_REGISTER_ARGTYPE for all argument types of slots and signals. Otherwise C++ has no way to get the type names needed for the MOC data generation.

See: https://github.com/woboq/verdigris/blob/master/tutorial/tutorial.cpp#L281

Please write a proper tutorial. Everytime I think I got it all then suddenly magic like this appears! They almost popped up from nowhere! W_REGISTER_ARGTYPE is also not on your Correspondance Table.

ghost commented 1 year ago

I have read the whole tutorial.cpp. It turned out to be even more complicated than CopperSpice, needs even more macros than CopperSpice to do the same thing. Without any automation tool like PepperMill, it's too much work to do. The Correspondance Table is incomplete, it gives the wrong impression that thing will be easy and straight forward. This is not for me. Goodbye.

arBmind commented 1 year ago

@iahung It seems you are looking for a different tool. Verdigris is not about making stuff simpler, but to make impossible things possible. Like templated QObjects. All while achieving the best runtime performance (unlike Copperspice) I hope you find what you are looking for.

ghost commented 1 year ago

@iahung It seems you are looking for a different tool. Verdigris is not about making stuff simpler, but to make impossible things possible. Like templated QObjects. All while achieving the best runtime performance (unlike Copperspice) I hope you find what you are looking for.

I like your moc-ng project more. You were right to create moc-ng. People need an drop-in replacement for moc, not a macros hack like this.

ogoffart commented 1 year ago

Both project started just as research project to find out what is possible.

Now, I don't think people need a drop-in replacement for moc. They probably want a better moc within Qt.

Then some people would be happy with a drop in replacement, and some people are happier without any moc at all, as verdigris showed, even if that means more complex macro and harder to decipher error messages.

But you're right that the documentation could be improved.