4
votes

I am just starting to get more familiar with how interfaces work so bear with me if this is a trivial question.

I have two plugins (call them A and B) in the form of DLLs (not packages). There is an interface with a GUID declared in application that loads the DLL, call it IMyInterface. Both plugins see the same interface definition with the same GUID. Plugin B actually implements the interface.

Plugin A wants to find out if plugin B supports the interface IMyInterface. I use obj.GetInterface (IMyInterface, IObj) to find this out:

var IObj : IMyInterface;
    obj : TObject;

obj := getPluginObjReference;

if obj.GetInterface(IMyInterface, IObj) then
   showmessage ('Interface Supported');

If I call this code within plugin B, the answer is yes, which is as expected. If I use the same code (cut and paste) in plugin A, the same code claims that plugin B does not support that interface. When I trace the GetInterface call into system.pas I find that InterfaceEntry := GetInterfaceEntry(IID); return nil, hence no interface to find.

For reference, IMyInterface looks like:

IMyInterface = interface
['{277A3122-A3F2-4A14-AE56-C99230F31CE9}']
   function getModel : AnsiString;
   function getDescription : AnsiString;
end;

and the implementation looks like:

// Now the real class, this is private to this plugin
TModelAPI = class (TInterfacedObject, IMyInterface)
   function getModel : AnsiString;
   function getDescription : AnsiString;
end;

etc.

My question:

As expected plugin B rightly claims that IMyInterface is supported. Why is it that Plugin A cannot discover that plugin B supports IMyInterface? Is there a problem with interrogating interfaces across DLL boundaries?

2
I am pleased to report that the answers given by ain and Heffernan provided the necessary information to solve the problem. I stopped passing objects and instead passed IInterface between the plugins, then I used the supports method to find out what interfaces were actually supported and this worked. I can now categorize plugins into what they reportedly can do. Many thanks for you help. The right answer goes to Heffernan because he gave a fuller answer but essentially both were right.rhody

2 Answers

7
votes

You cannot reliably pass objects across DLL boundaries. Instead you should pass interfaces across the boundary and use as or Supports to query capabilities. Interfaces are designed for binary compatibility across DLL boundaries, but objects are not.

You can readily pass an IInterface from one DLL to another and then query that. Or, if you have a common interface that all plugin objects implement, you could pass that. All that matters is that you always pass interfaces and never pass objects.

6
votes

You should really use only interfaces, ie the getPluginObjReference should return the lowest common interface supported by all the plugins and then you use Supports() function to test what interfaces (plugin versions) that particular plugin supports.