[英]Use C++-slot in QML which returns type in namespace
我首先要提到的是,以下工作正常到Qt 5.0.0 beta 1(也許是beta 2和RC也不知道),但在Qt 5.0.0最終版本中失敗了。 我只想參考Qt 5.0.0最終版本中看到的結果。 所以很可能這與Qt5最近的變化有關。
在C ++方面,我在命名空間中有一組類(QObject派生)(可選地用編譯器標志觸發;類在一個單獨的庫中,並且庫將命名空間的使用作為選項留給用戶使用圖書館)。 一個類,這里是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>
,只是在宏名稱中用“OAE”替換“QT”:
#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
。
其中,我從QML中為我的應用程序的用戶界面訪問此類的實例和由player()
返回的Player
類。 為此,我按如下方式注冊類:
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
生成以下“stringdata”,其中包含方法的返回類型:
禁用命名空間並使用返回類型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源代碼並查看了解析方法的位置,特別是返回類型(fyi,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)完成的
我認為“我們”可以將此稱為錯誤(或疏忽)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.