Hello, I'd like to present/discuss a recent helper I have developed which IMO simplifies the implementation of UNO services in C++ a lot. Using the following (what I call) service declaration, the developer can concentrate on implementing her service's interfaces, e.g.
class MyImpl : cppu::WeakImplHelper2<XInterface1, XInterface2> {...}; There is no need to implement lang::XServiceInfo nor lang::XInitialization (if the service expects arguments for creation). Next, one just has to declare the above class defining a service declaration object: namespace sdecl = comphelper::service_decl; sdecl::ServiceDecl const myDecl( sdecl::class_<MyImpl>(), "org.openoffice.MyService", [optional "my.implementation.name"] ); The ServiceDecl ctor expects as 1st parameter: a comphelper::service_decl::class_ object as first parameter (which I further explain shortly) 2nd parameter: a single name or a uno::Sequence<rtl::OUString> stating the supported service names 3rd parameter (optional): an implementation name; if this has been omitted, the implementation name will be generated out of MyImpl'S type_info (which I will explain shortly). The class_ object states the user's implementation class, which by default is required to define a constructor taking a uno::Reference<uno::XComponentContext> as its sole argument. If the user requires service arguments for construction, she can customize the class_ object, using sdecl::class_<MyImpl, sdecl::with_args<true> >() In this case, the user's implementation class is required to define a constuctor taking uno::Sequence<uno::Any>, uno::Reference<XComponentContext> If the user needs to execute "special" post processing code, e.g. for registering the newly created object as a listener, then she can specify a function/functor, too: sdecl::class_<MyImpl, ...>(&postProcessing) That functor needs to be of the following form, e.g. uno::Reference<uno::XInterface> postProcessing( MyClass * p ); and gets the _yet unacquired_ pointer. If the implementation name ought to be generated, then the mangled C++ name including the user's class is taken into account as well as the library name, e.g. a generated name may look like: "deployment680mi.uno.dll;[EMAIL PROTECTED]@dp_manager@@" (MSVC, using type_info::raw_name()) "deployment680li.uno.so;N10dp_manager7factory25PackageManagerFactoryImplE" (gcc 3.4.1, using type_info::name()) There is a flaw when the user uses an anonymous namespace for the implementation class: - At least on Windows there is the possibility that the generated implementation name is not unique (e.g. same anonymous class name in two different compilation units within same dll). - g++ mangles the whole compilation path into the anonymous symbol (+ time stamp etc.). This will avoid the possibility to just quickly compile and link a library with debug and exchange without re-registering it, which I fear leads to subtle confusion. IMO, sad but true, using a anonymous namespace is a bad idea here, so I currently disallow this leading to a runtime error when the library is loaded, stating these problems (currently on Windows only; easy to detect). Implementation classes have to be declared in a _named_ namespace (if any). When it comes to exporting the necessary component_xxx() functions, there are new helper functions that can deal with a variable number of ServiceDecl objects: extern "C" { void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** ) { *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; } sal_Bool SAL_CALL component_writeInfo( lang::XMultiServiceFactory * pServiceManager, registry::XRegistryKey * pRegistryKey ) { return component_writeInfoHelper( pServiceManager, pRegistryKey, myDecl, myDecl2, ... ); } void * SAL_CALL component_getFactory( sal_Char const * pImplName, lang::XMultiServiceFactory * pServiceManager, registry::XRegistryKey * pRegistryKey ) { return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey, myDecl, myDecl2, ...); } } // extern "C" By default, the component_xxxHelper() functions can cope with up to 8 declarations (can be increased using COMPHELPER_SERVICEHELPER_COMPONENT_HELPER_MAX_ARGS before including comphelper/servicedecl.hxx). You can have a look at the implementation on cws dbo510 (tag cws_src680_dbo510): comphelper/inc/comphelper/servicedecl.hxx comphelper/inc/comphelper/makesequence.hxx comphelper/source/misc/servicedecl.cxx For testing purposes, I have adopted the deployment API implementation (module desktop) which comes with quite a lot services. So what do you think? Comments, please. regards, -Daniel --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]