Added QMetaObjectFactory

This commit is contained in:
Filippo Cucchetto 2016-01-02 16:48:16 +01:00
parent 2ed13a3238
commit 3c63201936
7 changed files with 141 additions and 26 deletions

View File

@ -22,6 +22,7 @@ set(HEADERS_LIST
include/DOtherSide/DynamicQObjectFactory.h include/DOtherSide/DynamicQObjectFactory.h
include/DOtherSide/DynamicQObject.h include/DOtherSide/DynamicQObject.h
include/DOtherSide/Utils.h include/DOtherSide/Utils.h
include/DOtherSide/QMetaObjectFactory.h
) )
set(SRC_LIST set(SRC_LIST
@ -30,6 +31,7 @@ set(SRC_LIST
src/DynamicQObjectFactory.cpp src/DynamicQObjectFactory.cpp
src/DynamicQObject.cpp src/DynamicQObject.cpp
src/DOtherSideTypesCpp.cpp src/DOtherSideTypesCpp.cpp
src/QMetaObjectFactory.cpp
) )
include_directories(include include/Qt) include_directories(include include/Qt)

View File

@ -87,15 +87,11 @@ DOS_API void dos_qvariant_delete(void* vptr);
DOS_API void dos_qvariant_assign(void* vptr, void* other); DOS_API void dos_qvariant_assign(void* vptr, void* other);
// QObjectFactory // QObjectFactory
DOS_API void dos_qobjectfactory_create(void** vptr, DOS_API void dos_qmetaobjectfactory_create(void** vptr,
SignalDefinitions signalDefinitions, SignalDefinitions signalDefinitions,
SlotDefinitions slotDefinitions, SlotDefinitions slotDefinitions,
PropertyDefinitions propertyDefinitions); PropertyDefinitions propertyDefinitions);
DOS_API void dos_qobjectfactory_delete(void* vptr); DOS_API void dos_qmetaobjectfactory_delete(void* vptr);
DOS_API void dos_qobjectfactory_create_qobject(void* vptr,
void* dObjectPointer,
DObjectCallback dObjectCallback,
void** result);
// QObject // QObject
DOS_API void dos_qobject_signal_emit(void* vptr, DOS_API void dos_qobject_signal_emit(void* vptr,

View File

@ -22,9 +22,8 @@ struct SignalDefinition
SignalDefinition(::SignalDefinition cType) SignalDefinition(::SignalDefinition cType)
: name(QString::fromUtf8(cType.name)) : name(QString::fromUtf8(cType.name))
{ {
auto wrapped = wrap_array(cType.parametersMetaTypes, cType.parametersCount); for (int type : wrap_array(cType.parametersMetaTypes, cType.parametersCount))
auto conversion = [](int type)->QMetaType::Type { return static_cast<QMetaType::Type>(type);}; parameterTypes.emplace_back(QMetaType::Type(type));
std::transform(wrapped.begin(), wrapped.end(), parameterTypes.begin(), conversion);
} }
QString name; QString name;
@ -43,11 +42,10 @@ struct SlotDefinition
SlotDefinition(::SlotDefinition cType) SlotDefinition(::SlotDefinition cType)
: name(QString::fromUtf8(cType.name)) : name(QString::fromUtf8(cType.name))
, returnType(static_cast<QMetaType::Type>(cType.returnMetaType)) , returnType(QMetaType::Type(cType.returnMetaType))
{ {
auto wrapped = wrap_array(cType.parametersMetaTypes, cType.parametersCount); for (int type : wrap_array(cType.parametersMetaTypes, cType.parametersCount))
auto conversion = [](int type)->QMetaType::Type { return static_cast<QMetaType::Type>(type);}; parameterTypes.emplace_back(QMetaType::Type(type));
std::transform(wrapped.begin(), wrapped.end(), parameterTypes.begin(), conversion);
} }
QString name; QString name;

View File

@ -0,0 +1,52 @@
#pragma once
#include <memory>
#include <unordered_map>
#include <tuple>
#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtCore/QHash>
#include "DOtherSide/DOtherSideTypesCpp.h"
namespace DOS
{
class QMetaObjectFactory
{
public:
QMetaObjectFactory(SignalDefinitions signalDefinitions,
SlotDefinitions slotDefinitions,
PropertyDefinitions propertyDefinitions);
inline const QMetaObject* metaObject() const;
inline int signalSlotIndex(const QString& signalName) const;
inline int readSlotIndex(const char* propertyName) const;
inline int writeSlotIndex(const char* propertyName) const;
private:
SafeQMetaObjectPtr m_metaObject;
QHash<QByteArray, int> m_signalIndexByName;
QHash<QByteArray, QPair<int,int>> m_propertySlots;
};
const QMetaObject *QMetaObjectFactory::metaObject() const
{
return m_metaObject;
}
inline int QMetaObjectFactory::signalSlotIndex(const QString &signalName) const
{
return m_signalIndexByName.value(signalName.toUtf8(), -1);
}
inline int QMetaObjectFactory::readSlotIndex(const char *propertyName) const
{
return m_propertySlots.value(propertyName, {-1,-1}).first;
}
inline int QMetaObjectFactory::writeSlotIndex(const char *propertyName) const
{
return m_propertySlots.value(propertyName, {-1,-1}).second;
}
} // namespace DOS

View File

@ -29,7 +29,8 @@ std::vector<T> toVector(G* first, std::ptrdiff_t size) noexcept
{ {
const wrapped_array<G> array = wrap_array(first, size); const wrapped_array<G> array = wrap_array(first, size);
std::vector<T> result; std::vector<T> result;
std::copy(array.begin(), array.end(), result.begin()); for (auto it = array.begin(); it != array.end(); ++it)
result.emplace_back(T(*it));
return result; return result;
} }
@ -38,7 +39,8 @@ std::vector<R> toVector(T* first, std::ptrdiff_t size, K f) noexcept
{ {
wrapped_array<T> array = wrap_array<T>(first, size); wrapped_array<T> array = wrap_array<T>(first, size);
std::vector<R> result; std::vector<R> result;
std::transform(array.begin(), array.end(), result.begin(), f); for (auto it = array.begin(); it != array.end(); ++it)
result.emplace_back(R(f(*it)));
return result; return result;
} }
} }

View File

@ -514,7 +514,7 @@ void dos_qurl_to_string(void* vptr, char** result)
} }
void dos_qobjectfactory_create(void **vptr, void dos_qmetaobjectfactory_create(void **vptr,
SignalDefinitions signalDefinitions, SignalDefinitions signalDefinitions,
SlotDefinitions slotDefinitions, SlotDefinitions slotDefinitions,
PropertyDefinitions propertyDefinitions) PropertyDefinitions propertyDefinitions)
@ -524,14 +524,8 @@ void dos_qobjectfactory_create(void **vptr,
DOS::toVector(propertyDefinitions)); DOS::toVector(propertyDefinitions));
} }
void dos_qobjectfactory_delete(void *vptr) void dos_qmetaobjectfactory_delete(void *vptr)
{ {
auto factory = reinterpret_cast<DOS::DynamicQObjectFactory*>(vptr); auto factory = reinterpret_cast<DOS::DynamicQObjectFactory*>(vptr);
delete factory; 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(DOS::OnSlotExecutedHandler(dObjectPointer, dObjectCallback));
}

View File

@ -0,0 +1,71 @@
#include "DOtherSide/QMetaObjectFactory.h"
#include "private/qmetaobjectbuilder_p.h"
#include "private/qmetaobject_p.h"
#include "private/qobject_p.h"
namespace
{
template<class T>
QByteArray createSignature(const T& functionDefinition)
{
QString signature("%1(%2)");
QString arguments;
for (int type : functionDefinition.parameterTypes) {
if (type != functionDefinition.parameterTypes.front())
arguments += QLatin1Char(',');
arguments += QMetaType::typeName(type);
}
return signature.arg(functionDefinition.name, arguments).toUtf8();
}
}
namespace DOS
{
QMetaObjectFactory::QMetaObjectFactory(SignalDefinitions signalDefinitions,
SlotDefinitions slotDefinitions,
PropertyDefinitions propertyDefinitions)
: m_metaObject(nullptr)
{
QMetaObjectBuilder builder;
builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
builder.setClassName("DynamicQObject");
builder.setSuperClass(&QObject::staticMetaObject);
m_signalIndexByName.reserve(signalDefinitions.size());
for (const SignalDefinition& signal : signalDefinitions)
{
QMetaMethodBuilder signalBuilder = builder.addSignal(::createSignature(signal));
signalBuilder.setReturnType(QMetaType::typeName(QMetaType::Void));
signalBuilder.setAccess(QMetaMethod::Public);
m_signalIndexByName[signal.name.toUtf8()] = signalBuilder.index();
}
QHash<QString, int> methodIndexByName;
for (const SlotDefinition& slot : slotDefinitions)
{
QMetaMethodBuilder methodBuilder = builder.addSlot(::createSignature(slot));
methodBuilder.setReturnType(QMetaType::typeName(slot.returnType));
methodBuilder.setAttributes(QMetaMethod::Scriptable);
methodIndexByName[slot.name] = methodBuilder.index();
}
for (const PropertyDefinition& property : propertyDefinitions)
{
const int notifier = m_signalIndexByName.value(property.notifySignal.toUtf8(), -1);
const QByteArray name = property.name.toUtf8();
const QByteArray typeName = QMetaObject::normalizedType(QMetaType::typeName(property.type));
QMetaPropertyBuilder propertyBuilder = builder.addProperty(name, typeName, notifier);
if (notifier == -1)
propertyBuilder.setConstant(true);
m_propertySlots[propertyBuilder.name()] = { methodIndexByName.value(property.readSlot, -1)
, methodIndexByName.value(property.writeSlot, -1)};
}
m_metaObject.reset(builder.toMetaObject());
}
} // namespace DOS