summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--offapi/org/libreoffice/embindtest/XTest.idl3
-rw-r--r--static/source/embindmaker/embindmaker.cxx160
-rw-r--r--unotest/source/embindtest/embindtest.cxx22
-rw-r--r--unotest/source/embindtest/embindtest.js36
4 files changed, 212 insertions, 9 deletions
diff --git a/offapi/org/libreoffice/embindtest/XTest.idl b/offapi/org/libreoffice/embindtest/XTest.idl
index b3b5237ce2b4..8817e94669fc 100644
--- a/offapi/org/libreoffice/embindtest/XTest.idl
+++ b/offapi/org/libreoffice/embindtest/XTest.idl
@@ -113,6 +113,9 @@ interface XTest {
sequence<Struct> getSequenceStruct();
boolean isSequenceStruct([in] sequence<Struct> value);
void throwRuntimeException();
+ void passJob([in] com::sun::star::task::XJob object);
+ void passJobExecutor([in] com::sun::star::task::XJobExecutor object);
+ void passInterface([in] com::sun::star::uno::XInterface object);
};
}; }; };
diff --git a/static/source/embindmaker/embindmaker.cxx b/static/source/embindmaker/embindmaker.cxx
index 4241d10b1575..07214c289681 100644
--- a/static/source/embindmaker/embindmaker.cxx
+++ b/static/source/embindmaker/embindmaker.cxx
@@ -501,7 +501,7 @@ void dumpAttributes(std::ostream& out, rtl::Reference<TypeManager> const& manage
}
out << "->get" << attr.name << "(); }";
}
- out << ")\n";
+ out << ", ::emscripten::pure_virtual())\n";
if (!attr.readOnly)
{
out << " .function(\"set" << attr.name << "\", ";
@@ -530,7 +530,7 @@ void dumpAttributes(std::ostream& out, rtl::Reference<TypeManager> const& manage
}
out << "->set" << attr.name << "(the_value); }";
}
- out << ")\n";
+ out << ", ::emscripten::pure_virtual())\n";
}
}
}
@@ -660,7 +660,7 @@ void dumpWrapper(std::ostream& out, rtl::Reference<TypeManager> const& manager,
{
out << ", ::emscripten::allow_raw_pointers()";
}
- out << ")\n";
+ out << ", ::emscripten::pure_virtual())\n";
}
void dumpMethods(std::ostream& out, rtl::Reference<TypeManager> const& manager,
@@ -676,18 +676,18 @@ void dumpMethods(std::ostream& out, rtl::Reference<TypeManager> const& manager,
else
{
out << " .function(\"" << meth.name << "\", &" << cppName(name)
- << "::" << meth.name << ")\n";
+ << "::" << meth.name << ", ::emscripten::pure_virtual())\n";
}
}
}
-rtl::Reference<unoidl::InterfaceTypeEntity> resolveBase(rtl::Reference<TypeManager> const& manager,
- OUString const& name)
+rtl::Reference<unoidl::InterfaceTypeEntity>
+resolveInterface(rtl::Reference<TypeManager> const& manager, OUString const& name)
{
auto const ent = manager->getManager()->findEntity(name);
if (!ent.is() || ent->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
{
- throw CannotDumpException("bad interface base \"" + name + "\"");
+ throw CannotDumpException("bad interface \"" + name + "\"");
}
return static_cast<unoidl::InterfaceTypeEntity*>(ent.get());
}
@@ -695,7 +695,7 @@ rtl::Reference<unoidl::InterfaceTypeEntity> resolveBase(rtl::Reference<TypeManag
void recordVisitedBases(rtl::Reference<TypeManager> const& manager, OUString const& name,
std::set<OUString>& visitedBases)
{
- auto const ent = resolveBase(manager, name);
+ auto const ent = resolveInterface(manager, name);
for (auto const& base : ent->getDirectMandatoryBases())
{
if (visitedBases.insert(base.name).second)
@@ -709,7 +709,7 @@ void dumpBase(std::ostream& out, rtl::Reference<TypeManager> const& manager,
OUString const& interface, OUString const& name, std::set<OUString>& visitedBases,
std::list<OUString> const& baseTrail)
{
- auto const ent = resolveBase(manager, name);
+ auto const ent = resolveInterface(manager, name);
for (auto const& base : ent->getDirectMandatoryBases())
{
if (visitedBases.insert(base.name).second)
@@ -723,6 +723,126 @@ void dumpBase(std::ostream& out, rtl::Reference<TypeManager> const& manager,
dumpMethods(out, manager, interface, ent, baseTrail);
}
+void dumpWrapperClassMembers(std::ostream& out, rtl::Reference<TypeManager> const& manager,
+ OUString const& interface, OUString const& name,
+ std::set<OUString>& visitedBases)
+{
+ auto const ent = resolveInterface(manager, name);
+ for (auto const& base : ent->getDirectMandatoryBases())
+ {
+ if (visitedBases.insert(base.name).second)
+ {
+ dumpWrapperClassMembers(out, manager, interface, base.name, visitedBases);
+ }
+ }
+ for (auto const& attr : ent->getDirectAttributes())
+ {
+ out << " ";
+ dumpType(out, manager, attr.type);
+ out << " get" << attr.name << "() override { return call<";
+ dumpType(out, manager, attr.type);
+ out << ">(\"get" << attr.name << "\"); }\n";
+ if (!attr.readOnly)
+ {
+ out << " void set" << attr.name << "(";
+ dumpType(out, manager, attr.type);
+ switch (manager->getSort(resolveOuterTypedefs(manager, attr.type)))
+ {
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::Enum:
+ break;
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ case codemaker::UnoType::Sort::Sequence:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ case codemaker::UnoType::Sort::Interface:
+ out << " const &";
+ break;
+ default:
+ throw CannotDumpException("unexpected entity \"" + attr.type
+ + "\" as attribute type");
+ }
+ out << " the_value) override { return call<void>(\"set" << attr.name
+ << "\", the_value); }\n";
+ }
+ }
+ for (auto const& meth : ent->getDirectMethods())
+ {
+ out << " ";
+ dumpType(out, manager, meth.returnType);
+ out << " " << meth.name << "(";
+ bool first = true;
+ for (auto const& param : meth.parameters)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ out << ", ";
+ }
+ dumpType(out, manager, param.type);
+ if (param.direction == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN)
+ {
+ switch (manager->getSort(resolveOuterTypedefs(manager, param.type)))
+ {
+ case codemaker::UnoType::Sort::Boolean:
+ case codemaker::UnoType::Sort::Byte:
+ case codemaker::UnoType::Sort::Short:
+ case codemaker::UnoType::Sort::UnsignedShort:
+ case codemaker::UnoType::Sort::Long:
+ case codemaker::UnoType::Sort::UnsignedLong:
+ case codemaker::UnoType::Sort::Hyper:
+ case codemaker::UnoType::Sort::UnsignedHyper:
+ case codemaker::UnoType::Sort::Float:
+ case codemaker::UnoType::Sort::Double:
+ case codemaker::UnoType::Sort::Char:
+ case codemaker::UnoType::Sort::Enum:
+ break;
+ case codemaker::UnoType::Sort::String:
+ case codemaker::UnoType::Sort::Type:
+ case codemaker::UnoType::Sort::Any:
+ case codemaker::UnoType::Sort::Sequence:
+ case codemaker::UnoType::Sort::PlainStruct:
+ case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct:
+ case codemaker::UnoType::Sort::Interface:
+ out << " const &";
+ break;
+ default:
+ throw CannotDumpException("unexpected entity \"" + param.type
+ + "\" as parameter type");
+ }
+ }
+ else
+ {
+ out << " &";
+ }
+ out << " " << param.name;
+ }
+ out << ") override { return call<";
+ dumpType(out, manager, meth.returnType);
+ out << ">(\"" << meth.name << "\"";
+ for (auto const& param : meth.parameters)
+ {
+ out << ", " << param.name;
+ }
+ out << "); }\n";
+ }
+}
+
void dumpRegisterFunctionProlog(std::ostream& out, unsigned long long& counter)
{
out << "static void __attribute__((noinline)) register" << counter << "() {\n";
@@ -926,6 +1046,21 @@ SAL_IMPLEMENT_MAIN()
assert(ent.is());
assert(ent->getSort() == unoidl::Entity::SORT_INTERFACE_TYPE);
rtl::Reference const ifcEnt(static_cast<unoidl::InterfaceTypeEntity*>(ent.get()));
+ {
+ auto i = ifc.lastIndexOf('.');
+ auto j = i + 1;
+ if (i == -1)
+ {
+ i = 0;
+ }
+ cppOut << "namespace the_wrappers" << cppName(ifc.copy(0, i)) << " {\n"
+ << "struct " << ifc.copy(j) << " final: public ::emscripten::wrapper<"
+ << cppName(ifc) << "> {\n"
+ << " EMSCRIPTEN_WRAPPER(" << ifc.copy(j) << ");\n";
+ std::set<OUString> visitedBases;
+ dumpWrapperClassMembers(cppOut, mgr, ifc, ifc, visitedBases);
+ cppOut << "};\n}\n";
+ }
dumpRegisterFunctionProlog(cppOut, n);
cppOut << " ::emscripten::class_<" << cppName(ifc);
//TODO: Embind only supports single inheritance, so use that support at least for a UNO
@@ -938,9 +1073,16 @@ SAL_IMPLEMENT_MAIN()
}
cppOut << ">(\"uno_Type_" << jsName(ifc)
<< "\")\n"
+ " .allow_subclass<the_wrappers"
+ << cppName(ifc) << ">(\"uno_Wrapper_" << jsName(ifc)
+ << "\")\n"
" .smart_ptr<::com::sun::star::uno::Reference<"
<< cppName(ifc) << ">>(\"uno_Reference_" << jsName(ifc)
<< "\")\n"
+ " .class_function(\"reference\", +[]("
+ << cppName(ifc)
+ << " * the_interface) { return ::com::sun::star::uno::Reference(the_interface); "
+ "}, ::emscripten::allow_raw_pointers())\n"
" "
".constructor(+[](::com::sun::star::uno::Reference<::com::sun::star::uno::"
"XInterface> const & the_object) { return ::com::sun::star::uno::Reference<"
diff --git a/unotest/source/embindtest/embindtest.cxx b/unotest/source/embindtest/embindtest.cxx
index 39ba4c839dae..bcbb6d0ec870 100644
--- a/unotest/source/embindtest/embindtest.cxx
+++ b/unotest/source/embindtest/embindtest.cxx
@@ -9,11 +9,14 @@
#include <sal/config.h>
+#include <com/sun/star/task/XJob.hpp>
+#include <com/sun/star/task/XJobExecutor.hpp>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/RuntimeException.hpp>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/uno/XInterface.hpp>
#include <cppu/unotype.hxx>
#include <cppuhelper/implbase.hxx>
#include <cppuhelper/weak.hxx>
@@ -502,6 +505,25 @@ class Test : public cppu::WeakImplHelper<org::libreoffice::embindtest::XTest>
{
throw css::uno::RuntimeException(u"test"_ustr);
}
+
+ void SAL_CALL passJob(css::uno::Reference<css::task::XJob> const& object) override
+ {
+ object->execute({ { u"name"_ustr, css::uno::Any(u"job"_ustr) } });
+ }
+
+ void SAL_CALL
+ passJobExecutor(css::uno::Reference<css::task::XJobExecutor> const& object) override
+ {
+ object->trigger(u"executor"_ustr);
+ }
+
+ void SAL_CALL passInterface(css::uno::Reference<css::uno::XInterface> const& object) override
+ {
+ css::uno::Reference<css::task::XJob>(object, css::uno::UNO_QUERY_THROW)
+ ->execute({ { u"name"_ustr, css::uno::Any(u"queried job"_ustr) } });
+ css::uno::Reference<css::task::XJobExecutor>(object, css::uno::UNO_QUERY_THROW)
+ ->trigger(u"queried executor"_ustr);
+ }
};
}
diff --git a/unotest/source/embindtest/embindtest.js b/unotest/source/embindtest/embindtest.js
index 8c0ee0138828..749488cfa567 100644
--- a/unotest/source/embindtest/embindtest.js
+++ b/unotest/source/embindtest/embindtest.js
@@ -544,6 +544,42 @@ Module.addOnPostRun(function() {
console.assert(e.message === undefined); //TODO
//TODO: console.assert(e.Message.startsWith('test'));
}
+ const obj = {
+ refcount: 0,
+ queryInterface(type) {
+ if (type == 'com.sun.star.uno.XInterface') {
+ return new Module.uno_Any(type, css.uno.XInterface.reference(this.implXInterface));
+ } else if (type == 'com.sun.star.task.XJob') {
+ return new Module.uno_Any(type, css.task.XJob.reference(this.implXJob));
+ } else if (type == 'com.sun.star.task.XJobExecutor') {
+ return new Module.uno_Any(
+ type, css.task.XJobExecutor.reference(this.implXJobExecutor));
+ } else {
+ return new Module.uno_Any(Module.uno_Type.Void(), undefined);
+ }
+ },
+ acquire() { ++this.refcount; },
+ release() {
+ if (--this.refcount === 0) {
+ this.implXInterface.delete();
+ this.implXJob.delete();
+ this.implXJobExecutor.delete();
+ }
+ },
+ execute(args) {
+ console.log('Hello ' + args.get(0).Value.get());
+ return new Module.uno_Any(Module.uno_Type.Void(), undefined);
+ },
+ trigger(event) { console.log('Ola ' + event); }
+ };
+ obj.implXInterface = css.uno.XInterface.implement(obj);
+ obj.implXJob = css.task.XJob.implement(obj);
+ obj.implXJobExecutor = css.task.XJobExecutor.implement(obj);
+ obj.acquire();
+ test.passJob(css.task.XJob.reference(obj.implXJob));
+ test.passJobExecutor(css.task.XJobExecutor.reference(obj.implXJobExecutor));
+ test.passInterface(css.uno.XInterface.reference(obj.implXInterface));
+ obj.release();
});
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */