diff options
Diffstat (limited to 'cppuhelper/source/shlib.cxx')
-rw-r--r-- | cppuhelper/source/shlib.cxx | 77 |
1 files changed, 73 insertions, 4 deletions
diff --git a/cppuhelper/source/shlib.cxx b/cppuhelper/source/shlib.cxx index 0cffab6783f8..fa88cc4b484c 100644 --- a/cppuhelper/source/shlib.cxx +++ b/cppuhelper/source/shlib.cxx @@ -160,6 +160,70 @@ css::uno::Reference<css::uno::XInterface> invokeComponentFactory( } } +extern "C" void getInstance(va_list * args) { + cppuhelper::ImplementationConstructorFn * fn = va_arg(*args, cppuhelper::ImplementationConstructorFn *); + void * ctxt = va_arg(*args, void *); + assert(ctxt); + void * argseq = va_arg(*args, void *); + assert(argseq); + void ** instance = va_arg(*args, void **); + assert(instance); + assert(*instance == nullptr); + *instance = (*fn)(static_cast<css::uno::XComponentContext*>(ctxt), + *static_cast<css::uno::Sequence<css::uno::Any> const*>(argseq)); +} + +cppuhelper::WrapperConstructorFn mapConstructorFn( + css::uno::Environment const & source, css::uno::Environment const & target, + cppuhelper::ImplementationConstructorFn *const constructorFunction) +{ + if (!(source.is() && target.is())) { + throw css::loader::CannotActivateFactoryException( + "cannot get environments", + css::uno::Reference<css::uno::XInterface>()); + } + if (source.get() == target.get()) { + return cppuhelper::WrapperConstructorFn(constructorFunction); + } else { + // note: it should be valid to capture these mappings because they are + // ref-counted, and the returned closure will always be invoked in the + // "source" environment + css::uno::Mapping mapTo(source, target); + css::uno::Mapping mapFrom(target, source); + if (!(mapTo.is() && mapFrom.is())) { + throw css::loader::CannotActivateFactoryException( + "cannot get mappings", + css::uno::Reference<css::uno::XInterface>()); + } + return [mapFrom, mapTo, target, constructorFunction] + (css::uno::XComponentContext *const context, css::uno::Sequence<css::uno::Any> const& args) + { + void *const ctxt = mapTo.mapInterface( + context, + cppu::UnoType<css::uno::XComponentContext>::get()); + if (args.getLength() > 0) { + std::abort(); // TODO map args + } + void * instance = nullptr; + target.invoke(getInstance, constructorFunction, ctxt, &args, &instance); + if (ctxt != nullptr) { + (*target.get()->pExtEnv->releaseInterface)( + target.get()->pExtEnv, ctxt); + } + css::uno::XInterface * res = nullptr; + if (instance == nullptr) { + return res; + } + mapFrom.mapInterface( + reinterpret_cast<void **>(&res), instance, + cppu::UnoType<css::uno::XInterface>::get()); + (*target.get()->pExtEnv->releaseInterface)( + target.get()->pExtEnv, instance); + return res; + }; + } +} + } void cppuhelper::detail::loadSharedLibComponentFactory( @@ -167,13 +231,13 @@ void cppuhelper::detail::loadSharedLibComponentFactory( rtl::OUString const & prefix, rtl::OUString const & implementation, rtl::OUString const & constructor, css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager, - ImplementationConstructorFn ** constructorFunction, + WrapperConstructorFn * constructorFunction, css::uno::Reference<css::uno::XInterface> * factory) { assert(constructor.isEmpty() || !environment.isEmpty()); assert( (constructorFunction == nullptr && constructor.isEmpty()) - || *constructorFunction == nullptr); + || !*constructorFunction); assert(factory != nullptr && !factory->is()); #if defined DISABLE_DYNLOADING assert(!environment.isEmpty()); @@ -273,8 +337,13 @@ void cppuhelper::detail::loadSharedLibComponentFactory( + "\" in component library <" + uri + ">"), css::uno::Reference<css::uno::XInterface>()); } - *constructorFunction = reinterpret_cast<ImplementationConstructorFn *>( - fp); + css::uno::Environment curEnv(css::uno::Environment::getCurrent()); + *constructorFunction = mapConstructorFn( + curEnv, + (environment.isEmpty() + ? getEnvironmentFromModule(mod, curEnv, implementation, prefix) + : getEnvironment(environment, implementation)), + reinterpret_cast<ImplementationConstructorFn *>(fp)); } mod.release(); #endif |