我首先想提一下,以下内容在 Qt 5.0.0 beta 1 之前运行良好(也许 beta 2 和 RC 也是如此,不知道),但在 Qt 5.0.0 最终发布版本中失败。我只想引用Qt 5.0.0最终发布版本中看到的结果。所以很可能这与 Qt5 的最近变化有关。
在 C++ 方面,我在命名空间中有一组类(QObject 派生的)(可以选择用编译器标志触发;这些类在一个单独的库中,并且该库将命名空间的使用作为一个选项留给用户图书馆)。一个类(class),在这里Game
, 可能看起来像这样(摘录):
OAE_BEGIN_NAMESPACE
// forward-declarations:
class Player; // Player is just another class in the same library
class Game : public QObject
{
Q_OBJECT
public:
explicit Game(...);
public slots:
Player *player() const; // <-- the quesion is about such slots
};
OAE_END_NAMESPACE
宏
OAE_BEGIN/END_NAMESPACE
扩展为 namespace OAE_NAMESPACE {
... }
或者什么都不做,就像 Qt 在 <qglobal.h>
中所做的那样, 只是将宏名称中的“QT”替换为“OAE”:#ifndef OAE_NAMESPACE
# define OAE_PREPEND_NAMESPACE(name) ::name
# define OAE_USE_NAMESPACE
# define OAE_BEGIN_NAMESPACE
# define OAE_END_NAMESPACE
# define OAE_BEGIN_INCLUDE_NAMESPACE
# define OAE_END_INCLUDE_NAMESPACE
# define OAE_BEGIN_MOC_NAMESPACE
# define OAE_END_MOC_NAMESPACE
# define OAE_FORWARD_DECLARE_CLASS(name) class name;
# define OAE_FORWARD_DECLARE_STRUCT(name) struct name;
# define OAE_MANGLE_NAMESPACE(name) name
#else /* user namespace */
# define OAE_PREPEND_NAMESPACE(name) ::OAE_NAMESPACE::name
# define OAE_USE_NAMESPACE using namespace ::OAE_NAMESPACE;
# define OAE_BEGIN_NAMESPACE namespace OAE_NAMESPACE {
# define OAE_END_NAMESPACE }
# define OAE_BEGIN_INCLUDE_NAMESPACE }
# define OAE_END_INCLUDE_NAMESPACE namespace OAE_NAMESPACE {
# define OAE_BEGIN_MOC_NAMESPACE OAE_USE_NAMESPACE
# define OAE_END_MOC_NAMESPACE
# define OAE_FORWARD_DECLARE_CLASS(name) \
OAE_BEGIN_NAMESPACE class name; OAE_END_NAMESPACE \
using OAE_PREPEND_NAMESPACE(name);
# define OAE_FORWARD_DECLARE_STRUCT(name) \
OAE_BEGIN_NAMESPACE struct name; OAE_END_NAMESPACE \
using OAE_PREPEND_NAMESPACE(name);
# define OAE_MANGLE_NAMESPACE0(x) x
# define OAE_MANGLE_NAMESPACE1(a, b) a##_##b
# define OAE_MANGLE_NAMESPACE2(a, b) OAE_MANGLE_NAMESPACE1(a,b)
# define OAE_MANGLE_NAMESPACE(name) OAE_MANGLE_NAMESPACE2( \
OAE_MANGLE_NAMESPACE0(name), OAE_MANGLE_NAMESPACE0(OAE_NAMESPACE))
namespace OAE_NAMESPACE {}
# ifndef OAE_BOOTSTRAPPED
# ifndef OAE_NO_USING_NAMESPACE
/*
This expands to a "using OAE_NAMESPACE" also in _header files_.
It is the only way the feature can be used without too much
pain, but if people _really_ do not want it they can add
DEFINES += OAE_NO_USING_NAMESPACE to their .pro files.
*/
OAE_USE_NAMESPACE
# endif
# endif
#endif /* user namespace */
在下面,当说“启用命名空间”时,我的意思是我声明了宏
OAE_NAMESPACE
,在本例中为 oae
.其中,我访问此类的实例和
Player
player()
返回的类从 QML 中用于我的应用程序的用户界面。为此,我按如下方式注册类:qmlRegisterType<Game>();
qmlRegisterType<Player>();
我为 QML 前端提供了一个指向
Game
实例的指针。 ,称为 theGame
在 QML 中:view.engine()->rootContext()->setContextProperty("theGame",
QVariant::fromValue<Game*>(game));
在 QML 中,我像往常一样使用它。一个小例子应该打印
player()
的指针地址:Rectangle {
width: 100; height: 100
Component.onCompleted: console.log(theGame.player())
}
我得到以下结果,这取决于我是否设置了
OAE_NAMESPACE
与否(顺便说一句:我对使用它的库和应用程序使用相同的设置):QML 将指针打印给我:
Player(0x10b4ae0)
using
它在 C++ 代码中使用库,所以我根本不更改代码),QML 无法
了解
Game::player()
的返回类型:Error: Unknown method return type: Player*
Game::player()
到oae::Player*
,一切正常:oae::Player(0x10b4ae0)
到目前为止,我的结论是
moc
不考虑我在类周围放置的命名空间。我的第一个猜测是:嘿,moc
不知道我在调用 g++
时定义了命名空间,这就是我在 .pro 文件中所做的:DEFINES += OAE_NAMESPACE=oae
但是,当将返回类型更改为
OAE_NAMESPACE::Player*
时,它仍然有效,所以 moc 确实知道 OAE_NAMESPACE
宏,但它也不会扩展 OAE_BEGIN/END_NAMESPACE
宏或者它根本不再解析命名空间。moc
为 Player * Game::player() const
生成以下“字符串数据”其中包含方法的返回类型:Player*
:"player\0Player*\0"
Player*
:"player\0Player*\0"
OAE_NAMESPACE::Player*
:"player\0oae::Player*\0"
另一边,
moc
前置类名,由 QMetaObject::className()
返回如果启用,则带有命名空间。我现在的结论是我可以通过写
OAE_NAMESPACE::ClassName
来解决这个问题。而不是 ClassName
每当在 QObject 元方法的签名中使用这些类型时。 (嗯,有更好的宏 OAE_PREPEND_NAMESPACE
)。因为这在代码中看起来很糟糕,对我来说它甚至看起来是错误的,因为该方法已经在命名空间中,有更好的解决方案吗? 现在还有
OAE_BEGIN/END_MOC_NAMESPACE
(类似于 QT_BEGIN/END_MOC_NAMESPACE
)、所以也许我在任何地方都需要这些 ?我不知道它们在 Qt 中的何处/如何使用,所以我应该在我的库中相应地使用它们,因为我想使用与 Qt 相同的可选命名空间功能。
最佳答案
它真的适用于 5.0.0a 吗?
我浏览了 Qt 5.0.0 源代码并查看了解析方法的位置,尤其是返回类型(仅供引用,5.0.0\qtbase\src\tools\moc\moc.cpp:L160)并且没有命名空间检查(在参数,所以 player(Player* p)
也不起作用)。
而它是为类 def (5.0.0\qtbase\src\tools\moc\moc.cpp:L620 & L635) 完成的
我认为“我们”可以称之为错误(或疏忽)
关于c++ - 在 QML 中使用 C++-slot 返回命名空间中的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14086289/