簡體   English   中英

在QML中使用C ++ - slot,返回命名空間中的類型

[英]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宏,也不會完全解析命名空間。

mocPlayer * Game::player() const生成以下“stringdata”,其中包含方法的返回類型:

  • 禁用命名空間並使用返回類型Player*

     "player\\0Player*\\0" 
  • 啟用命名空間並使用返回類型Player*

     "player\\0Player*\\0" 
  • 啟用命名空間並使用返回類型OAE_NAMESPACE::Player*

     "player\\0oae::Player*\\0" 

另一方面,如果啟用了mocQMetaObject::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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM