Convenience macro do use Extension interfaces

Andreas Pakulat apaku at gmx.de
Thu Feb 15 14:21:50 UTC 2007


On 14.02.07 00:03:43, David Nolden wrote:
> Am Samstag, 10. Februar 2007 01:10 schrieb Andreas Pakulat:
> > this goes to all C++/CPP guru's that read this list.
> >
> > We need a convenience macro to implement the
> > register/unregisterExtensions however there's a slight problem: One
> > plugin can implement multiple interfaces, so we need something that
> > generates the functions during compile time from a list of interfaces.
> > Also we need to generate a proper factory for each interface the plugin
> > implements.
> >
> > See the KDEV_ADD_EXTENSION_INTERFACE and KDEV_USE_EXTENSION_INTERFACE
> > macros in iplugin.h to get an idea what code should be generated from
> > the macro.
> >
> > Hope somebody has a good idea, Matt threw the C++ Typelists into the
> > room...
> >
> > Andreas
> 
> I've worked with such things a lot for my teamwork-plugin, and know it quite 
> good.
> 
> I can help you, if you exactly tell me what there is to do. :)

Ok, lets say we have to interface IFaceA and IFaceB and a plugin class
called Plugin which implements both interfaces. Then we need the
following code to setup this plugin and register the interfaces with the
extensionmanager:

,----
| class PluginIFaceAFactory: public QExtensionFactory 
| {
| public:
|     PluginIFaceAFactory(QExtensionManager *parent = 0)
|         :QExtensionFactory(parent)
|     {
|         Q_UNUSED(parent)
|     }
|     protected:
|     virtual QObject *createExtension(QObject* object, const QString& iid, QObject* parent ) const
|     {
|         Q_UNUSED(parent) 
|         if( iid != Q_TYPEID( IFaceA ) )
|             return 0;
|         Plugin* p = qobject_cast<Plugin *>(object);
|         if( !p )
|             return 0;
|         return object;
|     }
| };
| 
| class PluginIFaceBFactory: public QExtensionFactory 
| {
| public:
|     PluginIFaceBFactory(QExtensionManager *parent = 0)
|         :QExtensionFactory(parent)
|     {
|         Q_UNUSED(parent)
|     }
|     protected:
|     virtual QObject *createExtension(QObject* object, const QString& iid, QObject* parent ) const
|     {
|         Q_UNUSED(parent) 
|         if( iid != Q_TYPEID( IFaceB ) )
|             return 0;
|         Plugin* p = qobject_cast<Plugin *>(object);
|         if( !p )
|             return 0;
|         return object;
|     }
| };
| 
| void Plugin::registerExtensions()
| {
|     extensionManager()->registerExtensions( new PluginIFaceAFactory(
|     extensionManager() ), Q_TYPEID( IFaceA ) );
|     extensionManager()->registerExtensions( new PluginIFaceBFactory(
|     extensionManager() ), Q_TYPEID( IFaceB ) );
| }
| void Plugin::unregisterExtensions()
| {
|     extensionManager()->unregisterExtensions( new QMakeImporterIFileManagerFactory(
|     extensionManager() ), Q_TYPEID( KDevelop::IFileManager ) );
|     extensionManager()->unregisterExtensions( new QMakeImporterIBuildManagerFactory(
|     extensionManager() ), Q_TYPEID( KDevelop::IBuildManager ) );
| }
| 
| QStringList Plugin::extensions() const
| {
|     return QStringList() << "IFaceA" << "IFaceB";
| }
`----

The two factories could theoretically be just one with two if (TYPEID)
clauses, but I guess that would make the whole thing more complicated.
The extensions() function doesn't necessarily be generated, I'm not even
sure we can make use of it. The factories are pretty easy to do and
there's already a macro for that, but the register functions are
problematic.

Also note: IFaceA and IFaceB can be inside a namespace, so eventually
there need to be 2 macro's one taking a classname and one taking a
namespace and a classname...

Andreas

-- 
You have a deep interest in all that is artistic.




More information about the KDevelop-devel mailing list