Using a Spawner

Spawners are used to create COM objects that are not servers. Often servers will need to create sub-objects of various types. Each of these sub-objects has two aspects, the ILxUnknownID interface handle that represents the COM object, and the internal C++ class pointer. For example suppose you want to implement a custom item type. For each item of your type that is created you’ll need to allocate an instance object with a PackageInstance interface.

1
2
3
4
5
6
 class CMyInstance : public CLxImpl_[[PackageInstance Interface|PackageInstance]]
 {
    public:
        LxResult         pins_Initialize (ILxUnknownID item, ILxUnknownID super) LXx_OVERRIDE;
        void             pins_Cleanup (void)                                     LXx_OVERRIDE;
 };

Like servers, spawners for sub-objects can be declared in the initialize() function. The process is quite similar. The spawner is created by allocating a polymorph template object for the class, and adding the supported interfaces, and registering the spawner under a name that must be unique only within this plug-in.

1
2
3
4
        void
 initialize ()
 {
        CLxGenericPolymorph     *srv;
1
2
3
4
        srv = new CLxPolymorph<CMyInstance>;
        srv->AddInterface (new CLxIfc_[[PackageInstance Interface|PackageInstance]]<CInstance>);
        lx::AddSpawner ("myInstance", srv);
 }

The spawner can be used by declaring a spawner object with the same type and name. The Alloc() method then creates a new sub-object, returning the C++ object directly and the COM object indirectly (in this case through the ppvObj pointer to the client).

1
2
3
4
5
6
         LxResult
 CPackage::pkg_Attach (
         void                  **ppvObj)
 {
         CLxSpawner<CMyInstance>  spawn ("myInstance");
         CMyInstance            *inst;
1
2
3
4
         inst = spawn.Alloc (ppvObj);
         inst->... = ...;             // init C++ object
         return LXe_OK;
 }

Spawners can also be used to get the internal C++ object from a COM object pointer. This does no checking so make sure that the object you pass is one of yours!

1
2
         CLxSpawner<CMyInstance>  spawn ("myInstance");
         CMyInstance            *inst;
1
         inst = spawn.Cast (externalObject);

It’s also possible to create spawners on the fly, allowing for functions that don’t require any initialization. The CLxSpawnerCreate class will find an existing spawner or create one. If it’s created then the interfaces can be initialized. If not it can just be used to allocate a new sub-object.

1
2
3
4
5
         CMyFoo *
 NewFooObject (
         ILxUnknownID           &obj)
 {
        CLxSpawnerCreate<CMyFoo> sp ("myFoo");
1
2
3
        if (sp.created) {
                sp.AddInterface (new CLxIfc_Foo<CMyFoo>);
        }
1
2
        return sp.Alloc (obj);
 }