Loading and Using a Plug-in

The code example in Listing 1 shows how a plug-in host can load and use a plug-in. It searches registered plug-ins for one that implements a test interface. If found, it invokes functions using the interface.

Listing 1  Loading and using a plug-in

Boolean foundInterface = false;
 
// Create a URL that points to the plug-in using a CFString path 'aPath'.
CFURLRef url =
    CFURLCreateWithFileSystemPath(NULL, aPath, kCFURLPOSIXPathStyle, TRUE);
 
// Create a CFPlugin using the URL.
// This causes the plug-in's types and factories to be registered with the system.
// The plug-in's code is not loaded unless it is using dynamic registration.
CFPlugInRef plugin = CFPlugInCreate(NULL, url);
 
if (!plugin)
{
    printf("Could not create CFPluginRef.\n");
}
else
{
    // Test whether this plug-in implements the Test type.
    CFArrayRef factories = CFPlugInFindFactoriesForPlugInType(kTestTypeID);
 
    // If there are factories for the requested type, attempt to
    // get the IUnknown interface.
    if (factories != NULL)
    {
        CFIndex factoryCount = CFArrayGetCount(factories);
 
        if (factoryCount <= 0)
        {
            printf("Could not find any factories.\n");
        }
        else
        {
            CFIndex index;
 
            for (index = 0;
                (index < factoryCount) && (!foundInterface);
                index++)
            {
                // Get the factory ID at the current index.
                CFUUIDRef factoryID =
                            CFArrayGetValueAtIndex(factories, index);
                // Use the factory ID to get an IUnknown interface.
                // The code for the PlugIn is loaded here.
                IUnknownVTbl **iunknown =
                    CFPlugInInstanceCreate(NULL, factoryID, kTestTypeID);
                // If this is an IUnknown interface,
                // query for the Test interface.
                if (iunknown)
                {
                    TestInterfaceStruct **interface = NULL;
                    (*iunknown)->QueryInterface(iunknown,
                                CFUUIDGetUUIDBytes(kTestInterfaceID),
                                (LPVOID *)(&interface));
                    // Finished with IUnknown.
                    (*iunknown)->Release(iunknown);
 
                    // If this is a Test interface, try to call its function.
                    if (interface)
                    {
                        (*interface)->fooMe(interface, TRUE);
                        (*interface)->fooMe(interface, FALSE);
                        // Finished with test interface.
                        // This causes the plug-in's code to be unloaded.
                        (*interface)->Release(interface);
 
                        foundInterface = true;
                    }
                }
                // end of iunknown
            }
            // end of index loop
        }
        // factoryCount > 0
 
        // Release the factories array.
        CFRelease(factories);
    }
    if (!foundInterface)
    {
        printf("Failed to get interface.\n");
    }
    // Release the CFPlugin -- memory for the plug-in is deallocated here.
    CFRelease(plugin);
}