Added QMetaObjectFactory
This commit is contained in:
parent
2ed13a3238
commit
3c63201936
|
@ -22,14 +22,16 @@ 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
|
||||||
src/DOtherSide.cpp
|
src/DOtherSide.cpp
|
||||||
src/OnSlotExecutedHandler.cpp
|
src/OnSlotExecutedHandler.cpp
|
||||||
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)
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#define DOS_API __declspec( dllexport )
|
#define DOS_API __declspec( dllexport )
|
||||||
#else
|
#else
|
||||||
#define DOS_API
|
#define DOS_API
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <DOtherSide/DOtherSideTypes.h>
|
#include <DOtherSide/DOtherSideTypes.h>
|
||||||
|
@ -48,7 +48,7 @@ DOS_API void dos_qquickview_set_source(void* vptr, const char* filename);
|
||||||
DOS_API void dos_qquickview_set_resize_mode(void* vptr, int resizeMode);
|
DOS_API void dos_qquickview_set_resize_mode(void* vptr, int resizeMode);
|
||||||
DOS_API void dos_qquickview_delete(void* vptr);
|
DOS_API void dos_qquickview_delete(void* vptr);
|
||||||
DOS_API void dos_qquickview_rootContext(void* vptr, void** result);
|
DOS_API void dos_qquickview_rootContext(void* vptr, void** result);
|
||||||
|
|
||||||
// QQmlContext
|
// QQmlContext
|
||||||
DOS_API void dos_qqmlcontext_baseUrl(void* vptr, char** result);
|
DOS_API void dos_qqmlcontext_baseUrl(void* vptr, char** result);
|
||||||
DOS_API void dos_qqmlcontext_setcontextproperty(void* vptr, const char* name, void* value);
|
DOS_API void dos_qqmlcontext_setcontextproperty(void* vptr, const char* name, void* value);
|
||||||
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue