最初に、以下はQt 5.0.0ベータ1までは正常に機能しましたが(おそらくベータ2とRCも、わかりません)、Qt5.0.0の最終リリースバージョンでは失敗します。Qt5.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
マクロは、Qtが実行するのと同じように、マクロ名で「QT」が「OAE」に置き換えられるだけで、 ...または何もOAE_BEGIN/END_NAMESPACE
展開されません。namespace OAE_NAMESPACE {
}
<qglobal.h>
#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フロントエンドに、QML内Game
で呼び出されるのインスタンスへのポインターを提供します。theGame
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()
私の結論は、QObjectメタメソッドのシグニチャでこれらのタイプを使用する代わりに、書き込むことでこれを修正できるということです。(まあ、より良いマクロがあります)。これはコードではひどいように見えますが、メソッドがすでに名前空間にあるため、私には間違っているように見えるので、より良い解決策はありますか?OAE_NAMESPACE::ClassName
ClassName
OAE_PREPEND_NAMESPACE
今はOAE_BEGIN/END_MOC_NAMESPACE
(に類似しているQT_BEGIN/END_MOC_NAMESPACE
)もあるので、多分私はどこかにそれらが必要ですか?Qtでどこでどのように使用されているかわからないので、Qtと同じオプションの名前空間機能を使用したいので、ライブラリでそれに応じて使用する必要があります。