[dev] proposal: ServiceDecl
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 {...}; 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_(), "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 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 as its sole argument. If the user requires service arguments for construction, she can customize the class_ object, using sdecl::class_ >() In this case, the user's implementation class is required to define a constuctor taking uno::Sequence, uno::Reference 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_(&postProcessing) That functor needs to be of the following form, e.g. uno::Reference 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]
Re: [dev] proposal: ServiceDecl
Daniel Boelzle <[EMAIL PROTECTED]> writes: > I'd like to present/discuss a recent helper I have developed which IMO > simplifies the implementation of UNO services in C++ a lot. > > [...] > > So what do you think? Comments, please. > Great stuff! Always having to write so much boilerplate has gotten to my nerves. One nit: since the automatic implementation name derivation looks kind of fragile (and most of the time, I _do_ declare my service implementations in anonymous namespaces) - how about disabling that feature by default? I have the impression that not much of OOo development outside Sun takes place on Windows, and specifying one (more) string at the constructor is really not that much overhead... Cheers, -- Thorsten If you're not failing some of the time, you're not trying hard enough. - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: [dev] proposal: ServiceDecl
> One nit: since the automatic implementation name derivation looks kind > of fragile (and most of the time, I _do_ declare my service > implementations in anonymous namespaces) - how about disabling that > feature by default? I have the impression that not much of OOo > development outside Sun takes place on Windows, and specifying one > (more) string at the constructor is really not that much overhead... Yes, the current implementation disallows the use of anonymous namespaces (at least on Windows, the dll cannot be registered). I agree, it is really not much work to specify an implementation name, but it would be nice to get rid of it. IMO the current (though not specified) rule inserting a "comp." into the service name to make an implementation name, e.g. "org.openoffice.package.MyService" => "org.openoffice.comp.package.MyService" is even more fragile. I think using a named namespace (instead of an anonymous) is not really overhead, and, with the prepended library name, the implementation name is unique: - double class definitions in the same library leads to link error - use of anonymous namespace for class_ leads to registration error Of course, the safe solution would be a globally unique identifier (GUID), but much more overhead. regards, -Daniel - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: [dev] proposal: ServiceDecl
Hi Daniel, > 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. again, you managed to make one of my recently-introduced helper classes (in a CWS not yet integrated) obsolete, with a much cooler solution. I hope you're not going to make a hobby out of this :) > class MyImpl : cppu::WeakImplHelper2 {...}; > > There is no need to implement lang::XServiceInfo nor Does this mean that at runtime, if an object of this class is instantiated, it in fact does not support XServiceInfo? Or do your factories create a wrapper around the real class, which adds this interface? Basically, can a Basic script developer still do something like: barServer = createUnoService( "com.sun.star.foo.BarServer" ) MsgBox barServer.ImplementationName ? > 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 Those are good candicates for cppuhelper, IMO. Thanks & Ciao Frank -- - Frank Schönheit, Software Engineer [EMAIL PROTECTED] - - Sun Microsystems http://www.sun.com/staroffice - - OpenOffice.org Database http://dba.openoffice.org - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: [dev] proposal: ServiceDecl
Daniel Boelzle wrote: namespace sdecl = comphelper::service_decl; sdecl::ServiceDecl const myDecl( sdecl::class_(), "org.openoffice.MyService", [optional "my.implementation.name"] ); If used as a global object, with a constructor that is executed when the DLL is loaded, that won't help with start-up performance. Niklas - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: [dev] proposal: ServiceDecl
Hello Frank, >>class MyImpl : cppu::WeakImplHelper2 {...}; >> >>There is no need to implement lang::XServiceInfo nor > > > Does this mean that at runtime, if an object of this class is > instantiated, it in fact does not support XServiceInfo? Or do your > factories create a wrapper around the real class, which adds this interface? > Basically, can a Basic script developer still do something like: > barServer = createUnoService( "com.sun.star.foo.BarServer" ) > MsgBox barServer.ImplementationName I wrap around, the object of course still supports lang::XServiceInfo at runtime; I am using cppu::ImplInheritanceHelper1. >>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 > > > Those are good candicates for cppuhelper, IMO. Yes, I think so. But for now, I would stick with comphelper, because the implementation uses boost (keep UDK/SDK free of boost stuff). regards, -Daniel - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: [dev] proposal: ServiceDecl
Hello Niklas, >>namespace sdecl = comphelper::service_decl; >>sdecl::ServiceDecl const myDecl( >>sdecl::class_(), >>"org.openoffice.MyService", >>[optional "my.implementation.name"] ); > > > If used as a global object, with a constructor that is executed when the > DLL is loaded, that won't help with start-up performance. IMO it doesn't matter whether you create that data (mostly the implementation name) at the point of loading the library or slightly later when the UNO service needs to be instantiated. But I agree that those ctors are executed even though not all services may be needed from that library, e.g. at the extreme if only one of 100 is used. Thus, it makes sense to optimize the current ctors, so they only save the passed char pointers, late-initializing OUString/Sequence objects when needed. For the case of multiple supported services we could e.g. use a separated list of service names like "Service1;Service2;...". All in all, I assume runtime performance is hardly affected then. regards, -Daniel - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: [dev] proposal: ServiceDecl
Hi Daniel, > IMO it doesn't matter whether you create that data (mostly the > implementation name) at the point of loading the library or slightly > later when the UNO service needs to be instantiated. It might be everything from "slightly later" to "never" (because perhaps sevice Foo from lib A is needed, but Bar isn't at all). I used to use the following pattern to prevent this: - implement extern "C" void SAL_CALL createServiceInfo_Foo() { static sdecl::ServiceDecl const myDecl( sdecl::class_(), "org.openoffice.Foo", "org.openoffice.comp.Foo" ); } beside my service implementation - call createServiceInfo_Foo from within component_* functions, for every implementation in the library This is slightly more uncomfortable than a global variable, but should prevent all its drawbacks. Ciao Frank -- - Frank Schönheit, Software Engineer [EMAIL PROTECTED] - - Sun Microsystems http://www.sun.com/staroffice - - OpenOffice.org Database http://dba.openoffice.org - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: [dev] proposal: ServiceDecl
Thorsten Behrens wrote: Daniel Boelzle <[EMAIL PROTECTED]> writes: I'd like to present/discuss a recent helper I have developed which IMO simplifies the implementation of UNO services in C++ a lot. [...] So what do you think? Comments, please. Great stuff! Always having to write so much boilerplate has gotten to my nerves. Of course it's a cool feature but i want to mention that the new skeletonmaker tool can help a lot to reduce the coding effort for UNO objects and components. The tool is not officially announced because there is still some work to do but you can start using it and give feedback. dump mode: - the tools can dump method declaration of interfaces and all supported interfaces of services to stdout so that you can easily copy this stuff in your source file. - it can generate complete method bodies to stdout (default return, forwarding, composition, inline or with classname, ...) component mode: - it can generate complete component skeletons (buidlable, deployable) and you have to concentrate on the real implementation only Supported languages Java and C++ More information will follow soon Juergen One nit: since the automatic implementation name derivation looks kind of fragile (and most of the time, I _do_ declare my service implementations in anonymous namespaces) - how about disabling that feature by default? I have the impression that not much of OOo development outside Sun takes place on Windows, and specifying one (more) string at the constructor is really not that much overhead... Cheers, - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]