diff options
-rw-r--r-- | cppuhelper/source/loadsharedlibcomponentfactory.hxx | 2 | ||||
-rw-r--r-- | cppuhelper/source/servicemanager.cxx | 45 | ||||
-rw-r--r-- | cppuhelper/source/servicemanager.hxx | 4 | ||||
-rw-r--r-- | cppuhelper/source/shlib.cxx | 77 |
4 files changed, 94 insertions, 34 deletions
diff --git a/cppuhelper/source/loadsharedlibcomponentfactory.hxx b/cppuhelper/source/loadsharedlibcomponentfactory.hxx index 7062d86fc494..df6e2269e381 100644 --- a/cppuhelper/source/loadsharedlibcomponentfactory.hxx +++ b/cppuhelper/source/loadsharedlibcomponentfactory.hxx @@ -35,7 +35,7 @@ void 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); } } diff --git a/cppuhelper/source/servicemanager.cxx b/cppuhelper/source/servicemanager.cxx index 780fe02ad70b..6d2321c3b9b1 100644 --- a/cppuhelper/source/servicemanager.cxx +++ b/cppuhelper/source/servicemanager.cxx @@ -686,9 +686,9 @@ cppuhelper::ServiceManager::Data::Implementation::createInstance( bool singletonRequest) { css::uno::Reference<css::uno::XInterface> inst; - if (constructor != nullptr) { + if (constructor) { inst.set( - (*constructor)(context.get(), css::uno::Sequence<css::uno::Any>()), + constructor(context.get(), css::uno::Sequence<css::uno::Any>()), SAL_NO_ACQUIRE); } else if (factory1.is()) { inst = factory1->createInstanceWithContext(context); @@ -706,8 +706,8 @@ cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments( bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments) { css::uno::Reference<css::uno::XInterface> inst; - if (constructor != nullptr) { - inst.set((*constructor)(context.get(), arguments), SAL_NO_ACQUIRE); + if (constructor) { + inst.set(constructor(context.get(), arguments), SAL_NO_ACQUIRE); //HACK: The constructor will either observe arguments and return inst // that does not implement XInitialization (or null), or ignore // arguments and return inst that implements XInitialization; this @@ -797,7 +797,7 @@ void cppuhelper::ServiceManager::loadImplementation( "Cannot expand URI" + implementation->info->uri + ": " + e.Message, static_cast< cppu::OWeakObject * >(this)); } - cppuhelper::ImplementationConstructorFn * ctor = nullptr; + cppuhelper::WrapperConstructorFn ctor; css::uno::Reference< css::uno::XInterface > f0; // Special handling of SharedLibrary loader, with support for environment, // constructor, and prefix arguments: @@ -808,27 +808,8 @@ void cppuhelper::ServiceManager::loadImplementation( uri, implementation->info->environment, implementation->info->prefix, implementation->info->name, implementation->info->constructor, this, &ctor, &f0); - if (ctor != nullptr) { + if (ctor) { assert(!implementation->info->environment.isEmpty()); - css::uno::Environment curEnv(css::uno::Environment::getCurrent()); - if (!curEnv.is()) { - throw css::uno::DeploymentException( - "cannot get current environment", - css::uno::Reference<css::uno::XInterface>()); - } - css::uno::Environment env( - cppuhelper::detail::getEnvironment( - implementation->info->environment, - implementation->info->name)); - if (!env.is()) { - throw css::uno::DeploymentException( - ("cannot get environment " - + implementation->info->environment), - css::uno::Reference<css::uno::XInterface>()); - } - if (curEnv.get() != env.get()) { - std::abort();//TODO - } } } else { SAL_WARN_IF( @@ -864,7 +845,7 @@ void cppuhelper::ServiceManager::loadImplementation( } css::uno::Reference<css::lang::XSingleComponentFactory> f1; css::uno::Reference<css::lang::XSingleServiceFactory> f2; - if (ctor == nullptr) { + if (!ctor) { f1.set(f0, css::uno::UNO_QUERY); if (!f1.is()) { f2.set(f0, css::uno::UNO_QUERY); @@ -1978,7 +1959,15 @@ void cppuhelper::ServiceManager::preloadImplementations() { else { // get function symbol component factory - fpFactory = aModule.getFunctionSymbol(iterator->second->info->constructor); + aTargetEnv = cppuhelper::detail::getEnvironment(iterator->second->info->environment, iterator->second->info->name); + if (aSourceEnv.get() == aTargetEnv.get()) + { + fpFactory = aModule.getFunctionSymbol(iterator->second->info->constructor); + } + else + { + fpFactory = nullptr; + } } css::uno::Reference<css::lang::XSingleComponentFactory> xSCFactory; @@ -2002,7 +1991,7 @@ void cppuhelper::ServiceManager::preloadImplementations() { } if (!iterator->second->info->constructor.isEmpty() && fpFactory) - iterator->second->constructor = reinterpret_cast<ImplementationConstructorFn *>(fpFactory); + iterator->second->constructor = WrapperConstructorFn(reinterpret_cast<ImplementationConstructorFn *>(fpFactory)); iterator->second->factory1 = xSCFactory; iterator->second->factory2 = xSSFactory; diff --git a/cppuhelper/source/servicemanager.hxx b/cppuhelper/source/servicemanager.hxx index ca0021370545..5f6efd094dd5 100644 --- a/cppuhelper/source/servicemanager.hxx +++ b/cppuhelper/source/servicemanager.hxx @@ -50,6 +50,8 @@ typedef css::uno::XInterface * SAL_CALL ImplementationConstructorFn( } +typedef std::function<css::uno::XInterface * (css::uno::XComponentContext *, css::uno::Sequence<css::uno::Any> const&)> WrapperConstructorFn; + typedef cppu::WeakComponentImplHelper< css::lang::XServiceInfo, css::lang::XMultiServiceFactory, css::lang::XMultiComponentFactory, css::container::XSet, @@ -149,7 +151,7 @@ public: enum Status { STATUS_NEW, STATUS_WRAPPER, STATUS_LOADED }; std::shared_ptr< ImplementationInfo > info; - ImplementationConstructorFn * constructor; + WrapperConstructorFn constructor; css::uno::Reference< css::lang::XSingleComponentFactory > factory1; css::uno::Reference< css::lang::XSingleServiceFactory > factory2; css::uno::Reference< css::lang::XComponent > component; 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 |