[objective-C] Accessing other plugins in runtime

Hi,

I am currently writing multiple plugins entirely in objective-C, and I want them to communicate with each other.

The problem is, I couldn’t find a way to import each other’s headers in the source file.

I found out that if you write a plugin in Python, the contents of every other installed plugins are accessible (i.e. their paths are appended to sys.path, so you can import them).

Is there a similar way to dynamically link another installed plugin using objective-C??

1 Like

While I was waiting my question to be approved and uploaded to the forum, I think I found a hint.

By using NSClassFromString:@“MyPluginName” method, apparently I can access the class method of the plugin I made.

I am thinking of implementing a singleton pattern to access not only the class methods, but also all instance methods.

If anyone have a better -or easier- solution, it’d be great to know!

You can access everything from other plugins. The connection is not done by importing the headers. That is just telling the compiler what the other object can do. In your case, add the headers to both plugins. Or define a protocol that each plugin implements:

Then you do:

id<GlyphsFilter> removeOverlapFilter = [[NSClassFromString(@"GlyphsFilterRemoveOverlap") alloc] init];

The you can use that object normally:

[removeOverlapFilter runFilterWithLayer:layer error:nil];

You need to check the result of NSClassFromString and show an error message that the other plugin is missing.

Or, depending what you are trying to do, put everything into one plugin. There are callbacks for most things that you can add broader functionality. e.g. reporter can handle mouse commands and file-format plugins can draw.

1 Like

Your answer made it clear what i was thinking wrong.

I just could add headers to inform one plugin what the others are capable of, without actually increasing the compiled size of the plugin.

Thanks very much!

What a great idea to access plugins from each other. I never really thought about that, even though I often had an unconscious guts feeling that it would be incredibly handy from time to time. I think I’ll give it a try, as well. Thanks for the inspirational thread!

1 Like

There are two things to know.

  • If you “link” to some code (as you do to the GlyphsCore framework), then you can use the classes directly ([[GlyphsFilterRemoveOverlap alloc] init];). because the linking tells the code where to find that class. If you don’t link to it, you still can get to the class but that is an active lookup in the runtime. So in performance critical code it might be a good idea to cache the class.
  • When you call a method, the runtime doesn’t know much about the object you are calling the method on. It doesn’t know about the header and all the definitions there. Those are only help the compiler give you some feedback.

So in cases like this, you need to be really careful when you load a class from a different plugins. You should never change the API because you never know if the user has the most recent version of both plugins. Or if you have to change the API your code needs to check if the loaded plugins are the right version.

1 Like

Thinking about that, changing a method name used by another plugin will cause an app crash.

Thanks for the warning!!
I should minimize the inter-plugin communications and check every access whether it is possible.

There is the very useful [someObject respondsToSelector:@selector(methodName)], I use that a lot.

2 Likes