Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find out if an object supports a given interface (between two DLLs)

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?

like image 431
rhody Avatar asked Dec 13 '22 07:12

rhody


2 Answers

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.

like image 84
David Heffernan Avatar answered May 25 '23 23:05

David Heffernan


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.

like image 32
ain Avatar answered May 25 '23 23:05

ain