Added DynamicQObjectFactory methods to C interface
This commit is contained in:
parent
83893b2934
commit
711131b4f4
|
@ -16,6 +16,7 @@ find_package(Qt5Widgets)
|
|||
set(HEADERS_LIST
|
||||
include/DOtherSide/BaseQAbstractListModel.h
|
||||
include/DOtherSide/DOtherSideTypes.h
|
||||
include/DOtherSide/DOtherSideTypesCpp.h
|
||||
include/DOtherSide/DynamicSignal.h
|
||||
include/DOtherSide/BaseQObject.h
|
||||
include/DOtherSide/DynamicProperty.h
|
||||
|
@ -26,6 +27,7 @@ set(HEADERS_LIST
|
|||
include/DOtherSide/OnSlotExecutedHandler.h
|
||||
include/DOtherSide/DynamicQObjectFactory.h
|
||||
include/DOtherSide/DynamicQObject2.h
|
||||
include/DOtherSide/Utils.h
|
||||
)
|
||||
|
||||
set(SRC_LIST
|
||||
|
@ -36,6 +38,7 @@ set(SRC_LIST
|
|||
src/DynamicProperty.cpp
|
||||
src/DynamicQObjectFactory.cpp
|
||||
src/DynamicQObject2.cpp
|
||||
src/DOtherSideTypesCpp.cpp
|
||||
)
|
||||
|
||||
include_directories(include include/Qt)
|
||||
|
|
|
@ -169,6 +169,17 @@ DOS_API void dos_qurl_create(void** vptr, const char* url, int parsingMode);
|
|||
DOS_API void dos_qurl_delete(void* vptr);
|
||||
DOS_API void dos_qurl_to_string(void* vptr, char** result);
|
||||
|
||||
// QObjectFactory
|
||||
DOS_API void dos_qobjectfactory_create(void** vptr,
|
||||
SignalDefinitions signalDefinitions,
|
||||
SlotDefinitions slotDefinitions,
|
||||
PropertyDefinitions propertyDefinitions);
|
||||
DOS_API void dos_qobjectfactory_delete(void* vptr);
|
||||
DOS_API void dos_qobjectfactory_create_qobject(void* vptr,
|
||||
void* dObjectPointer,
|
||||
DObjectCallback dObjectCallback,
|
||||
void** result);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -30,6 +30,48 @@ typedef void(*RoleNamesCallback)(void* model, QHashIntQByteArrayVoidPtr result);
|
|||
typedef void(*FlagsCallback) (void* model, QModelIndexVoidPtr index, IntPtr result);
|
||||
typedef void(*HeaderDataCallback) (void* model, int section, int orientation, int role, QVariantVoidPtr result);
|
||||
|
||||
struct SignalDefinition
|
||||
{
|
||||
const char* name;
|
||||
int parametersCount;
|
||||
int* parametersMetaTypes;
|
||||
};
|
||||
|
||||
struct SignalDefinitions
|
||||
{
|
||||
int count;
|
||||
SignalDefinition* definitions;
|
||||
};
|
||||
|
||||
struct SlotDefinition
|
||||
{
|
||||
const char* name;
|
||||
int returnMetaType;
|
||||
int parametersCount;
|
||||
int* parametersMetaTypes;
|
||||
};
|
||||
|
||||
struct SlotDefinitions
|
||||
{
|
||||
int count;
|
||||
SlotDefinition* definitions;
|
||||
};
|
||||
|
||||
struct PropertyDefinition
|
||||
{
|
||||
const char* name;
|
||||
int propertyMetaType;
|
||||
const char* readSlot;
|
||||
const char* writeSlot;
|
||||
const char* notifySignal;
|
||||
};
|
||||
|
||||
struct PropertyDefinitions
|
||||
{
|
||||
int count;
|
||||
PropertyDefinition* definitions;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
#pragma once
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QMetaType>
|
||||
|
||||
#include "DOtherSide/DOtherSideTypes.h"
|
||||
#include "DOtherSide/Utils.h"
|
||||
|
||||
namespace DOS
|
||||
{
|
||||
struct SignalDefinition
|
||||
{
|
||||
SignalDefinition(QString n,
|
||||
std::vector<QMetaType::Type> v)
|
||||
: name(std::move(n))
|
||||
, parameterTypes(std::move(v))
|
||||
{}
|
||||
|
||||
SignalDefinition(::SignalDefinition cType)
|
||||
: name(QString::fromUtf8(cType.name))
|
||||
{
|
||||
auto wrapped = wrap_array(cType.parametersMetaTypes, cType.parametersCount);
|
||||
auto conversion = [](int type)->QMetaType::Type { return static_cast<QMetaType::Type>(type);};
|
||||
std::transform(wrapped.begin(), wrapped.end(), parameterTypes.begin(), conversion);
|
||||
}
|
||||
|
||||
QString name;
|
||||
std::vector<QMetaType::Type> parameterTypes;
|
||||
};
|
||||
|
||||
struct SlotDefinition
|
||||
{
|
||||
SlotDefinition(QString n,
|
||||
QMetaType::Type t,
|
||||
std::vector<QMetaType::Type> v)
|
||||
: name(std::move(n))
|
||||
, returnType(std::move(t))
|
||||
, parameterTypes(std::move(v))
|
||||
{}
|
||||
|
||||
SlotDefinition(::SlotDefinition cType)
|
||||
: name(QString::fromUtf8(cType.name))
|
||||
, returnType(static_cast<QMetaType::Type>(cType.returnMetaType))
|
||||
{
|
||||
auto wrapped = wrap_array(cType.parametersMetaTypes, cType.parametersCount);
|
||||
auto conversion = [](int type)->QMetaType::Type { return static_cast<QMetaType::Type>(type);};
|
||||
std::transform(wrapped.begin(), wrapped.end(), parameterTypes.begin(), conversion);
|
||||
}
|
||||
|
||||
QString name;
|
||||
QMetaType::Type returnType;
|
||||
std::vector<QMetaType::Type> parameterTypes;
|
||||
};
|
||||
|
||||
struct PropertyDefinition
|
||||
{
|
||||
PropertyDefinition(QString n,
|
||||
QMetaType::Type t,
|
||||
QString r,
|
||||
QString w,
|
||||
QString s)
|
||||
: name(std::move(n))
|
||||
, type(std::move(t))
|
||||
, readSlot(std::move(r))
|
||||
, writeSlot(std::move(w))
|
||||
, notifySignal(std::move(s))
|
||||
{}
|
||||
|
||||
PropertyDefinition(::PropertyDefinition cType)
|
||||
: name(cType.name)
|
||||
, type(static_cast<QMetaType::Type>(cType.propertyMetaType))
|
||||
, readSlot(QString::fromUtf8(cType.readSlot))
|
||||
, writeSlot(QString::fromUtf8(cType.writeSlot))
|
||||
, notifySignal(QString::fromUtf8(cType.notifySignal))
|
||||
{}
|
||||
|
||||
QString name;
|
||||
QMetaType::Type type;
|
||||
QString readSlot;
|
||||
QString writeSlot;
|
||||
QString notifySignal;
|
||||
};
|
||||
|
||||
using SignalDefinitions = std::vector<SignalDefinition>;
|
||||
using SlotDefinitions = std::vector<SlotDefinition>;
|
||||
using PropertyDefinitions = std::vector<PropertyDefinition>;
|
||||
|
||||
SignalDefinitions toVector(const ::SignalDefinitions& cType);
|
||||
SlotDefinitions toVector(const ::SlotDefinitions& cType);
|
||||
PropertyDefinitions toVector(const ::PropertyDefinitions& cType);
|
||||
|
||||
}
|
|
@ -3,12 +3,15 @@
|
|||
#include <QObject>
|
||||
#include <functional>
|
||||
|
||||
namespace DOS
|
||||
{
|
||||
|
||||
class DynamicQObjectFactory;
|
||||
|
||||
class DynamicQObject2 : public QObject
|
||||
{
|
||||
public:
|
||||
using OnSlotExecuted = std::function<QVariant(int, const QString&, const std::vector<QVariant>&)>;
|
||||
using OnSlotExecuted = std::function<QVariant(const QString&, const std::vector<QVariant>&)>;
|
||||
|
||||
DynamicQObject2(const DynamicQObjectFactory* factory,
|
||||
OnSlotExecuted handler);
|
||||
|
@ -25,3 +28,5 @@ private:
|
|||
const DynamicQObjectFactory* const m_factory;
|
||||
const OnSlotExecuted m_handler;
|
||||
};
|
||||
|
||||
} // namespace DOS
|
||||
|
|
|
@ -3,48 +3,28 @@
|
|||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <tuple>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QHash>
|
||||
|
||||
struct SignalDefinition
|
||||
{
|
||||
QString name;
|
||||
std::vector<QMetaType::Type> argumentsTypes;
|
||||
};
|
||||
#include "DOtherSide/DOtherSideTypesCpp.h"
|
||||
|
||||
struct SlotDefinition
|
||||
namespace DOS
|
||||
{
|
||||
QString name;
|
||||
QMetaType::Type returnType;
|
||||
std::vector<QMetaType::Type> argumentsTypes;
|
||||
};
|
||||
|
||||
struct PropertyDefinition
|
||||
{
|
||||
QString name;
|
||||
QMetaType::Type type;
|
||||
QString readSlot;
|
||||
QString writeSlot;
|
||||
QString notifySignal;
|
||||
};
|
||||
|
||||
class DynamicQObject2;
|
||||
|
||||
class DynamicQObjectFactory
|
||||
{
|
||||
using SignalDefinitions = std::vector<SignalDefinition>;
|
||||
using SlotDefinitions = std::vector<SlotDefinition>;
|
||||
using PropertyDefinitions = std::vector<PropertyDefinition>;
|
||||
using SafeQMetaObjectPtr = std::unique_ptr<QMetaObject, void(*)(void*)>;
|
||||
using OnSlotExecuted = std::function<QVariant(int, const QString&, const std::vector<QVariant>&)>;
|
||||
using OnSlotExecuted = std::function<QVariant(const QString&, const std::vector<QVariant>&)>;
|
||||
|
||||
public:
|
||||
DynamicQObjectFactory(SignalDefinitions signalDefinitions,
|
||||
SlotDefinitions slotDefinitions,
|
||||
PropertyDefinitions propertyDefinitions);
|
||||
|
||||
|
||||
DynamicQObject2* create(OnSlotExecuted handler) const;
|
||||
inline const QMetaObject* metaObject() const;
|
||||
inline int signalSlotIndex(const QString& signalName) const;
|
||||
|
@ -76,3 +56,5 @@ inline int DynamicQObjectFactory::writeSlotIndex(const char *propertyName) const
|
|||
{
|
||||
return m_propertySlots.value(propertyName, {-1,-1}).second;
|
||||
}
|
||||
|
||||
} // namespace DOS
|
||||
|
|
|
@ -14,7 +14,8 @@ class OnSlotExecutedHandler
|
|||
public:
|
||||
OnSlotExecutedHandler(void* dObjectPointer, IDynamicQObject::Callback dObjectCallback);
|
||||
|
||||
QVariant operator()(const DynamicSlot& slot, std::vector<QVariant> const& args);
|
||||
QVariant operator()(const QString& name, const std::vector<QVariant>& args);
|
||||
QVariant operator()(const DynamicSlot& slot, const std::vector<QVariant>& args);
|
||||
|
||||
private:
|
||||
void* m_dObjectPointer;
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace DOS
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct wrapped_array {
|
||||
wrapped_array(T* first, T* last) : begin_ {first}, end_ {last} {}
|
||||
wrapped_array(T* first, std::ptrdiff_t size)
|
||||
: wrapped_array {first, first + size} {}
|
||||
|
||||
T* begin() const noexcept { return begin_; }
|
||||
T* end() const noexcept { return end_; }
|
||||
|
||||
T* begin_;
|
||||
T* end_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
wrapped_array<T> wrap_array(T* first, std::ptrdiff_t size) noexcept
|
||||
{ return {first, size}; }
|
||||
|
||||
template <typename T, typename G>
|
||||
std::vector<T> toVector(const wrapped_array<G>& array)
|
||||
{
|
||||
std::vector<T> result;
|
||||
std::copy(array.begin(), array.end(), result.begin());
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -13,10 +13,14 @@
|
|||
#include <QtQuick/QQuickView>
|
||||
#include <QtWidgets/QApplication>
|
||||
|
||||
#include "DOtherSide/DOtherSideTypesCpp.h"
|
||||
#include "DOtherSide/DynamicQObject.h"
|
||||
#include "DOtherSide/BaseQAbstractListModel.h"
|
||||
#include "DOtherSide/BaseQObject.h"
|
||||
#include "DOtherSide/OnSlotExecutedHandler.h"
|
||||
#include "DOtherSide/DynamicQObjectFactory.h"
|
||||
#include "DOtherSide/DynamicQObject2.h"
|
||||
|
||||
|
||||
void convert_to_cstring(const QString& source, char** destination)
|
||||
{
|
||||
|
@ -649,3 +653,25 @@ void dos_qurl_to_string(void* vptr, char** result)
|
|||
convert_to_cstring(url->toString(), result);
|
||||
}
|
||||
|
||||
|
||||
void dos_qobjectfactory_create(void **vptr,
|
||||
SignalDefinitions signalDefinitions,
|
||||
SlotDefinitions slotDefinitions,
|
||||
PropertyDefinitions propertyDefinitions)
|
||||
{
|
||||
*vptr = new DOS::DynamicQObjectFactory(DOS::toVector(signalDefinitions),
|
||||
DOS::toVector(slotDefinitions),
|
||||
DOS::toVector(propertyDefinitions));
|
||||
}
|
||||
|
||||
void dos_qobjectfactory_delete(void *vptr)
|
||||
{
|
||||
auto factory = reinterpret_cast<DOS::DynamicQObjectFactory*>(vptr);
|
||||
delete factory;
|
||||
}
|
||||
|
||||
void dos_qobjectfactory_create_qobject(void *vptr, void* dObjectPointer, DObjectCallback dObjectCallback, void **result)
|
||||
{
|
||||
auto factory = reinterpret_cast<DOS::DynamicQObjectFactory*>(vptr);
|
||||
*result = factory->create(OnSlotExecutedHandler(dObjectPointer, dObjectCallback));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#include "DOtherSide/DOtherSideTypesCpp.h"
|
||||
|
||||
namespace DOS {
|
||||
|
||||
SignalDefinitions toVector(const ::SignalDefinitions& cType)
|
||||
{
|
||||
return toVector<SignalDefinition, ::SignalDefinition>(wrap_array(cType.definitions, cType.count));
|
||||
}
|
||||
|
||||
SlotDefinitions toVector(const ::SlotDefinitions& cType)
|
||||
{
|
||||
return toVector<SlotDefinition, ::SlotDefinition>(wrap_array(cType.definitions, cType.count));
|
||||
}
|
||||
|
||||
PropertyDefinitions toVector(const ::PropertyDefinitions& cType)
|
||||
{
|
||||
return toVector<PropertyDefinition, ::PropertyDefinition>(wrap_array(cType.definitions, cType.count));
|
||||
}
|
||||
}
|
|
@ -3,6 +3,9 @@
|
|||
#include <QtCore/QMetaMethod>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
namespace DOS
|
||||
{
|
||||
|
||||
DynamicQObject2::DynamicQObject2(const DynamicQObjectFactory *factory,
|
||||
OnSlotExecuted handler)
|
||||
: m_factory(factory)
|
||||
|
@ -63,7 +66,7 @@ bool DynamicQObject2::executeSlot(int index, void **args)
|
|||
arguments.emplace_back(std::move(argument));
|
||||
}
|
||||
|
||||
QVariant result = m_handler(index, method.name(), arguments); // Execute method
|
||||
QVariant result = m_handler(method.name(), arguments); // Execute method
|
||||
|
||||
if (method.returnType() != QMetaType::Void && result.isValid()) {
|
||||
QMetaType::construct(method.returnType(), args[0], result.constData());
|
||||
|
@ -91,3 +94,5 @@ bool DynamicQObject2::writeProperty(int index, void **args)
|
|||
}
|
||||
return executeSlot(m_factory->writeSlotIndex(property.name()), args);
|
||||
}
|
||||
|
||||
} // namespace DOS
|
||||
|
|
|
@ -6,23 +6,28 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
template<class T>
|
||||
QByteArray createSignature(const T& functionDefinition)
|
||||
{
|
||||
QString signature("%1(%2)");
|
||||
QString arguments;
|
||||
template<class T>
|
||||
QByteArray createSignature(const T& functionDefinition)
|
||||
{
|
||||
QString signature("%1(%2)");
|
||||
QString arguments;
|
||||
|
||||
for (QMetaType::Type type : functionDefinition.argumentsTypes) {
|
||||
if (type != functionDefinition.argumentsTypes.front())
|
||||
arguments += QLatin1Char(',');
|
||||
arguments += QMetaType::typeName(type);
|
||||
}
|
||||
|
||||
return signature.arg(functionDefinition.name, arguments).toUtf8();
|
||||
for (int type : functionDefinition.parameterTypes) {
|
||||
if (type != functionDefinition.parameterTypes.front())
|
||||
arguments += QLatin1Char(',');
|
||||
arguments += QMetaType::typeName(type);
|
||||
}
|
||||
|
||||
return signature.arg(functionDefinition.name, arguments).toUtf8();
|
||||
}
|
||||
}
|
||||
|
||||
DynamicQObjectFactory::DynamicQObjectFactory(DynamicQObjectFactory::SignalDefinitions signalDefinitions, DynamicQObjectFactory::SlotDefinitions slotDefinitions, DynamicQObjectFactory::PropertyDefinitions propertyDefinitions)
|
||||
namespace DOS
|
||||
{
|
||||
|
||||
DynamicQObjectFactory::DynamicQObjectFactory(SignalDefinitions signalDefinitions,
|
||||
SlotDefinitions slotDefinitions,
|
||||
PropertyDefinitions propertyDefinitions)
|
||||
: m_metaObject(nullptr, ::free)
|
||||
{
|
||||
QMetaObjectBuilder builder;
|
||||
|
@ -34,7 +39,7 @@ DynamicQObjectFactory::DynamicQObjectFactory(DynamicQObjectFactory::SignalDefini
|
|||
|
||||
for (const SignalDefinition& signal : signalDefinitions)
|
||||
{
|
||||
QMetaMethodBuilder signalBuilder = builder.addSignal(createSignature(signal));
|
||||
QMetaMethodBuilder signalBuilder = builder.addSignal(::createSignature(signal));
|
||||
signalBuilder.setReturnType(QMetaType::typeName(QMetaType::Void));
|
||||
signalBuilder.setAccess(QMetaMethod::Public);
|
||||
m_signalIndexByName[signal.name.toUtf8()] = signalBuilder.index();
|
||||
|
@ -43,7 +48,7 @@ DynamicQObjectFactory::DynamicQObjectFactory(DynamicQObjectFactory::SignalDefini
|
|||
QHash<QString, int> methodIndexByName;
|
||||
for (const SlotDefinition& slot : slotDefinitions)
|
||||
{
|
||||
QMetaMethodBuilder methodBuilder = builder.addSlot(createSignature(slot));
|
||||
QMetaMethodBuilder methodBuilder = builder.addSlot(::createSignature(slot));
|
||||
methodBuilder.setReturnType(QMetaType::typeName(slot.returnType));
|
||||
methodBuilder.setAttributes(QMetaMethod::Scriptable);
|
||||
methodIndexByName[slot.name] = methodBuilder.index();
|
||||
|
@ -68,3 +73,5 @@ DynamicQObject2* DynamicQObjectFactory::create(OnSlotExecuted handler) const
|
|||
{
|
||||
return new DynamicQObject2(this, std::move(handler));
|
||||
}
|
||||
|
||||
} // namespace DOS
|
||||
|
|
|
@ -7,7 +7,7 @@ OnSlotExecutedHandler::OnSlotExecutedHandler(void *dObjectPointer,
|
|||
, m_dObjectCallback(dObjectCallback)
|
||||
{}
|
||||
|
||||
QVariant OnSlotExecutedHandler::operator()(const DynamicSlot& slot, const std::vector<QVariant> &args)
|
||||
QVariant OnSlotExecutedHandler::operator()(const QString &name, const std::vector<QVariant> &args)
|
||||
{
|
||||
QVariant result;
|
||||
|
||||
|
@ -15,7 +15,7 @@ QVariant OnSlotExecutedHandler::operator()(const DynamicSlot& slot, const std::v
|
|||
return result;
|
||||
|
||||
// prepare slot name
|
||||
QVariant slotName(slot.name());
|
||||
QVariant slotName(name);
|
||||
|
||||
// prepare void* for the QVariants
|
||||
std::vector<void*> argumentsAsVoidPointers;
|
||||
|
@ -29,3 +29,8 @@ QVariant OnSlotExecutedHandler::operator()(const DynamicSlot& slot, const std::v
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariant OnSlotExecutedHandler::operator()(const DynamicSlot& slot, const std::vector<QVariant> &args)
|
||||
{
|
||||
return operator ()(slot.name(), args);
|
||||
}
|
||||
|
|
|
@ -100,21 +100,22 @@ private slots:
|
|||
}
|
||||
|
||||
void benchmarkDynamicQObject2Performance() {
|
||||
|
||||
QBENCHMARK {
|
||||
DynamicQObjectFactory factory {{SignalDefinition{"fooChanged", {QMetaType::Int}}},
|
||||
{SlotDefinition{"foo", QMetaType::Int, {}}, SlotDefinition{"setFoo", QMetaType::Void, {QMetaType::Int}}},
|
||||
{PropertyDefinition{"foo", QMetaType::Int, "foo", "setFoo", "fooChanged"}}};
|
||||
DOS::DynamicQObjectFactory factory {{DOS::SignalDefinition{"fooChanged", {QMetaType::Int}}},
|
||||
{DOS::SlotDefinition{"foo", QMetaType::Int, {}}, DOS::SlotDefinition{"setFoo", QMetaType::Void, {QMetaType::Int}}},
|
||||
{DOS::PropertyDefinition{"foo", QMetaType::Int, "foo", "setFoo", "fooChanged"}}};
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
std::unique_ptr<DynamicQObject2> dynamicQObject(factory.create([](int, const QString&, const std::vector<QVariant>&)-> QVariant{}));
|
||||
std::unique_ptr<DOS::DynamicQObject2> dynamicQObject(factory.create([](const QString&, const std::vector<QVariant>&)-> QVariant{}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testDynamicQObject2() {
|
||||
DynamicQObjectFactory factory {{SignalDefinition{"fooChanged", {QMetaType::Int}}},
|
||||
{SlotDefinition{"foo", QMetaType::Int, {}}, SlotDefinition{"setFoo", QMetaType::Void, {QMetaType::Int}}},
|
||||
{PropertyDefinition{"foo", QMetaType::Int, "foo", "setFoo", "fooChanged"}}};
|
||||
std::unique_ptr<DynamicQObject2> dynamicQObject(factory.create([](int, const QString&, const std::vector<QVariant>&)-> QVariant{}));
|
||||
DOS::DynamicQObjectFactory factory {{DOS::SignalDefinition{"fooChanged", {QMetaType::Int}}},
|
||||
{DOS::SlotDefinition{"foo", QMetaType::Int, {}}, DOS::SlotDefinition{"setFoo", QMetaType::Void, {QMetaType::Int}}},
|
||||
{DOS::PropertyDefinition{"foo", QMetaType::Int, "foo", "setFoo", "fooChanged"}}};
|
||||
std::unique_ptr<DOS::DynamicQObject2> dynamicQObject(factory.create([](const QString&, const std::vector<QVariant>&)-> QVariant{}));
|
||||
QVERIFY(dynamicQObject != nullptr);
|
||||
|
||||
QSignalSpy signalSpy(dynamicQObject.get(), SIGNAL(fooChanged(int)));
|
||||
|
|
Loading…
Reference in New Issue