On 08/16/2011 10:37 PM, Lex Trotman wrote:
Hi All,
Given that the previous thread had moved way off topic, I started this one.
After thinking about it a bit, considering Matthew's, Colomban's and Thomas's comments and looking at other systems I came to the understanding documented below. Frank probably already knew all this, but I have saved him writing lots of English. If its right and you think its worth using in the newsletter or anywhere else feel free to copy it.
Great information, this should most certainly go into the Wiki (as well as any other useful places).
A plugin must have been compiled with a version of Geany with the same ABI as the one it is being loaded into. This ensures that nothing has been removed, no semantics have changed and none of the low level bit patterns have changed.
Geany must also supply at least the functions the plugin needs, so the API must be greater than that needed by the plugin.
These two checks are done by the PLUGIN_VERSION_CHECK macro.
Actually, I think usually the checks end up being done by GModule/dlopen since they try to load the plugin and bail-out when they get undefined symbol errors. Only after that is when the PLUGIN_VERSION_CHECK macro would have a chance to do it's checks. I could be completely wrong on this, but I think it's what I've observed.
Plugins that wish to use newer features but still support older versions can only make the decision at compile time because the API number of the Geany that the plugin is being loaded into isn't available at runtime. Making the API number available at runtime may be a potential enhancement of the interface and allow plugins to support a wider range of versions.
Wouldn't run-time be too late anyway, since the undefined functions didn't have a chance to get pre-processed out according the version?
Like:
void some_func(void) { if (geany_check_api_version(189)) undefined_function_here(); /* dlopen error */ }
The API and ABI number pair should be published (in release notes?) when a release is made for use by plugin packagers.
+1 ... Franks list on the Wiki is an great start!
IMO, it's quite useful/important that each function/member's doc-comments be annotated with the API version number as well, as has been discussed. This would let developers reading the API docs know *exactly* which API version they should check against to use a certain thing, even between releases.
This means that:
- the interface should be as small as possible so that the least
possible changes impact the ABI.
- structures should not be visible in the interface, instead they
should be hidden behind getter/setter functions, and
++1 ... This would be great.
Most importantly (I think) is that you could do whatever you want with the struct members without breaking API/ABI compatibility and such, since they would be opaque.
- interface wrapper functions should be used to hide the
implementation and side effects.
+1
The last two have not been Geany policy to date but I now propose that they be.
I agree wholeheartedly.
A bit O/T, but it would also be great to get rid of the need for those pesky globals `geany_plugin`, `geany_data`, and `geany_functions` required to defined/included in each TU of the plugin. At least for the first two, they could (one already is) be just passed into the plugin's entry-point (plugin_init()). As for `geany_functions`, I'm not sure, since all those weird macros in `geanyfunctions.h` require it.
Cheers, Matthew Brush