In my app I have Q_INVOKABLE
function that returns a naked pointer to a QObject
owned by std::shared_ptr
:
namespace tradeclient
{
class OrderModel : public QObject
{
Q_OBJECT
public:
Q_PROPERTY(QString marketId READ marketId CONSTANT)
Q_PROPERTY(quint64 id READ id CONSTANT)
signals:
void failed(qint64 code, QString message);
...
};
using OrderPtr = std::shared_ptr<OrderModel>;
class MarketModel : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE tradeclient::OrderModel* createLimitOrder()
{
return m_orders.front().get();
}
private:
//In my app I initialize OrderModel-s and add them so some container and set C++ ownership.
std::vector<OrderPtr> m_orders;
};
} //namespace tradeclient
Q_DECLARE_METATYPE(tradeclient::OrderPtr)
and I am trying to invent a way to use std::shared_ptr
from both C++ and QML.
I did various experimentation with Q_DECLARE_SMART_POINTER_METATYPE and came to the conclusion that is useless in my app because it does not expose wrapped object properties to QML.
As the next experiment I tried to declare a gadget containing std::shared_ptr
as a member:
namespace tradeclient
{
class OrderGadget
{
Q_GADGET
Q_PROPERTY(tradeclient::OrderModel* p READ pointer);
public:
OrderGadget() = default;
OrderGadget(OrderPtr p) : m_p(std::move(p)) {}
private:
tradeclient::OrderModel* pointer()
{
return m_p.get();
}
OrderPtr m_p;
};
}
Q_DECLARE_METATYPE(tradeclient::OrderGadget)
return it from createLimitOrder()
as follows:
namespace tradeclient
{
using OrderPtr = std::shared_ptr<OrderModel>;
class MarketModel : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE tradeclient::OrderGadget createLimitOrder()
{
return m_orders.front();
}
private:
//Leave default ownership.
std::vector<OrderPtr> m_orders;
};
}
and access OrderModel
object via p
property in QML:
var shared_order = market.createLimitOrder()
var order = shared_order.p
if (order)
{
console.log("Qml", "Limit order type: %1, value: %2, id: %3".arg(typeof(order)).arg(JSON.stringify(order)).arg(order.marketId))
order.failed.connect((code, message) => { window.showFading("%1 order has failed: %2".arg(shared_order.p.marketId).arg(message))})
}
else
console.log("Qml", "The order is not defined.");
This QML code prints object properties:
Limit order type: object, value: {"objectName":"","marketId":"BTCUSDT","id":0,"side":0 ...
and connects to failed
signal.
But it is not clear enough is this code correct. Is it possible that GC will delete order
variable after the order object already destroyed by std::shared_ptr
?
What is the lifetime of failed
handler function that refers shared_order
?