diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 64aa6dd..c375e08 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -22,14 +22,16 @@ set(HEADERS_LIST include/DOtherSide/DynamicQObjectFactory.h include/DOtherSide/DynamicQObject.h include/DOtherSide/Utils.h + include/DOtherSide/QMetaObjectFactory.h ) -set(SRC_LIST +set(SRC_LIST src/DOtherSide.cpp src/OnSlotExecutedHandler.cpp src/DynamicQObjectFactory.cpp src/DynamicQObject.cpp src/DOtherSideTypesCpp.cpp + src/QMetaObjectFactory.cpp ) include_directories(include include/Qt) diff --git a/lib/include/DOtherSide/DOtherSide.h b/lib/include/DOtherSide/DOtherSide.h index 4d6335f..a8639a8 100644 --- a/lib/include/DOtherSide/DOtherSide.h +++ b/lib/include/DOtherSide/DOtherSide.h @@ -4,7 +4,7 @@ #ifdef WIN32 #define DOS_API __declspec( dllexport ) #else -#define DOS_API +#define DOS_API #endif #include @@ -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_delete(void* vptr); DOS_API void dos_qquickview_rootContext(void* vptr, void** result); - + // QQmlContext DOS_API void dos_qqmlcontext_baseUrl(void* vptr, char** result); 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); // QObjectFactory -DOS_API void dos_qobjectfactory_create(void** vptr, +DOS_API void dos_qmetaobjectfactory_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); +DOS_API void dos_qmetaobjectfactory_delete(void* vptr); // QObject DOS_API void dos_qobject_signal_emit(void* vptr, diff --git a/lib/include/DOtherSide/DOtherSideTypesCpp.h b/lib/include/DOtherSide/DOtherSideTypesCpp.h index 73836fd..40283d6 100644 --- a/lib/include/DOtherSide/DOtherSideTypesCpp.h +++ b/lib/include/DOtherSide/DOtherSideTypesCpp.h @@ -22,9 +22,8 @@ struct SignalDefinition 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(type);}; - std::transform(wrapped.begin(), wrapped.end(), parameterTypes.begin(), conversion); + for (int type : wrap_array(cType.parametersMetaTypes, cType.parametersCount)) + parameterTypes.emplace_back(QMetaType::Type(type)); } QString name; @@ -43,11 +42,10 @@ struct SlotDefinition SlotDefinition(::SlotDefinition cType) : name(QString::fromUtf8(cType.name)) - , returnType(static_cast(cType.returnMetaType)) + , returnType(QMetaType::Type(cType.returnMetaType)) { - auto wrapped = wrap_array(cType.parametersMetaTypes, cType.parametersCount); - auto conversion = [](int type)->QMetaType::Type { return static_cast(type);}; - std::transform(wrapped.begin(), wrapped.end(), parameterTypes.begin(), conversion); + for (int type : wrap_array(cType.parametersMetaTypes, cType.parametersCount)) + parameterTypes.emplace_back(QMetaType::Type(type)); } QString name; diff --git a/lib/include/DOtherSide/QMetaObjectFactory.h b/lib/include/DOtherSide/QMetaObjectFactory.h new file mode 100644 index 0000000..9b49459 --- /dev/null +++ b/lib/include/DOtherSide/QMetaObjectFactory.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include + +#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 m_signalIndexByName; + QHash> 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 diff --git a/lib/include/DOtherSide/Utils.h b/lib/include/DOtherSide/Utils.h index a974d75..0e77e18 100644 --- a/lib/include/DOtherSide/Utils.h +++ b/lib/include/DOtherSide/Utils.h @@ -29,7 +29,8 @@ std::vector toVector(G* first, std::ptrdiff_t size) noexcept { const wrapped_array array = wrap_array(first, size); std::vector 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; } @@ -38,7 +39,8 @@ std::vector toVector(T* first, std::ptrdiff_t size, K f) noexcept { wrapped_array array = wrap_array(first, size); std::vector 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; } } diff --git a/lib/src/DOtherSide.cpp b/lib/src/DOtherSide.cpp index 783152e..ca570d5 100644 --- a/lib/src/DOtherSide.cpp +++ b/lib/src/DOtherSide.cpp @@ -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, SlotDefinitions slotDefinitions, PropertyDefinitions propertyDefinitions) @@ -524,14 +524,8 @@ void dos_qobjectfactory_create(void **vptr, DOS::toVector(propertyDefinitions)); } -void dos_qobjectfactory_delete(void *vptr) +void dos_qmetaobjectfactory_delete(void *vptr) { auto factory = reinterpret_cast(vptr); delete factory; } - -void dos_qobjectfactory_create_qobject(void *vptr, void* dObjectPointer, DObjectCallback dObjectCallback, void **result) -{ - auto factory = reinterpret_cast(vptr); - *result = factory->create(DOS::OnSlotExecutedHandler(dObjectPointer, dObjectCallback)); -} diff --git a/lib/src/QMetaObjectFactory.cpp b/lib/src/QMetaObjectFactory.cpp new file mode 100644 index 0000000..2a68a8b --- /dev/null +++ b/lib/src/QMetaObjectFactory.cpp @@ -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 +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 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