Author Topic: Hi  (Read 5924 times)

vongodric

  • Guest
Hi
« on: February 04, 2006, 12:14:48 am »
Hi everyone,

First wanna say that code::blocks is really great -I'm switching all my dev'ing over  8) Really good work guys!

Now I had also a small question ( wasn't sure into wich topic this belongs ) -I'm developing an IDE as well, but it's for FreeBASIC compiler and is very different from code::blocks ( using c++ and wxWidgets ) and I was playing with the idea of implementing plugin support for my next major release. I'v been looking into the subject a bit ( and also browsing code::blocks source code ), but could someone be so kind and shortly describe what is the best approach to take and reasonable way to implement plugins? Mostly I'd add plugins for helper tools( like code auto formatting/indenting or exporting into html/rtf/..., maybe RAD tool? and the likes )

Thanks.

ps! my "IDE's" website: http://www.fbide.freebasic.net/

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Hi
« Reply #1 on: February 04, 2006, 12:37:52 am »
There are several ways to provide plugins.

The most portable is to embed a scripting engine (of any kind) and write all plugins in that scripting language. Firefox works like this, for example.

Another solution is to build plugins as dynamically linked library with a defined interface. Code::Blocks uses that approach. The intimidating word "interface" means nothing but some known symbol (usually a function with a well-known signature) which is exported by the library (so the application can import it).

There are several ways to design the interface, the easiest way is to export a few C functions, but you can as well define the interface via a C++ class (Code::Blocks does that).

Whatever you choose, you have to ensure that
a) the interface does not change once it is released (or else all plugins will break)
b) plugin developers comply with what you define as the interface

The easiest (least painful) way to guarantee that plugin developers comply with the interface is to make a C++ class from which they derive their plugin.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

vongodric

  • Guest
Re: Hi
« Reply #2 on: February 04, 2006, 12:54:30 am »
This is something I had in mind ( pretty much the code::blocks approach ).

To have a base class that provides base set of methods and from what actual plugin is derived. The rest is upto for a plugin developer.

My drafts and a sort of working test that I have so far.
http://cvs.sourceforge.net/viewcvs.py/fbide/FBIde/fbipe/

But I just want some background information before really starting designing potential system of my own. External scripting is I think a way limited and slow. Though no doubt is easy for plugin writer and developer. Doesn't code::block support some scripting capablities? ( I was under impression it provided angel scripting? ).


Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Hi
« Reply #3 on: February 04, 2006, 01:16:52 am »
Quote
This is something I had in mind ( pretty much the code::blocks approach ).
[...]
My drafts and a sort of working test that I have so far.
You should add something like a "C" GetPlugin() global function which is exported and which returns new YourPlugin. There are of course a hundred other ways to do it, this is just what I would do...
Also, I recommend that you build in some versioning and sanity checking functionality. This can be as easy as exporting a constant, or a function like GetVersion() or something. Anything will do, but you should have a way of telling whether the plugin will send your application straight to hell - in that case, the application should refuse to load it.
Personally, I would also keep the header file near the source, but that is a matter of taste. In any case, think clearly about the filesystem layout now and make any changes that you might make some day now, because the less files you have, the less trouble you have.

Quote
External scripting is I think a way limited and slow. Though no doubt is easy for plugin writer and developer.
It really depends on what you want and what you need, and on who is your audience. If you expect your plugins being written by users who don't necessarily know a lot about programming, then Python may very well be a consideration (although I personally hate Python, it still has advantages you can't deny). On the other hand, if you expect your plugins to be written by professionals, then I'd recommend C++.
Inkscape effects are all Python or Perl scripts, Blender supports a large part of its functionality only through Python (almost all file import/exports are done that way, and many, many effects), Firefox extensions do everything using JavaScript... there are more examples that could be used as proof of concept that it works and that it is fast enough on today's hardware.
But generally, you are right. Scripting is of course at least 10-15 times slower than native code.

Quote
Doesn't code::block support some scripting capablities?
Yes, Code::Blocks supports AngelScript. But we still write plugins in C++. It is faster, and a plugin has more power (in fact, a plugin has the same capability as the main program).
« Last Edit: February 04, 2006, 01:18:41 am by thomas »
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

vongodric

  • Guest
Re: Hi
« Reply #4 on: February 04, 2006, 01:32:37 am »
Quote
You should add something like a "C" GetPlugin() global function which is exported and which returns new YourPlugin.
This is eactly what I did with my test app  :wink:
Quote
I recommend that you build in some versioning and sanity checking functionality
Yes I thought of it as well. I think there should be version checking where plugin checks host system's version and vise versa. Where main program checks SDK version or smth? Maybe some security number or and string. becouse it is possible that some random dll happens to have same global functions. Unlikely thoo  :)
Quote
It really depends on what you want and what you need, and on who is your audience
Mostly I want ( from my part ) to provide tools for my ide so I won't have to hardcode them into an editor. In most cases these are helper tools and the like. Maybe some wizard like things that guides user through some steps and generates starting code? But few people already have said that they'd be interested in adding rad and cvs plugins -of course this remains to be seen. So I think C++ based are really the best choice for me.



Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Hi
« Reply #5 on: February 04, 2006, 01:47:50 am »
Quote
This is eactly what I did with my test app  :wink:
Ah, I only looked at the PluginClass header, and saw no such thing there. I'd put everything that belongs to the plugin SDK into one file.
Exporting this access function and the version info can conveniently be done via a macro that you define in the plugin SDK header. I am normally very strictly against macros, no matter for what purpose. But in this case, a macro really makes your life easier. Look how Code::Blocks does it.

Quote
Yes I thought of it as well. I think there should be version checking where plugin checks host system's version and vise versa.
Either way works if everybody is persistent in doing it. The easiest way is to have a compile-time constant in the header, so every plugin has a version number (which can be accessed directly as symbol or via an accessor function). When the application is updated, you update the number in the header, too. The application can then decide not to load plugins with a too low version number.
Alternatively, you can provide something like GetMinVersion() and GetMaxVersion() as virtual (or pure virtual) functions, or you can really put the responsibility of checking the version into the plugin developer's hands. In that case, you must export symbols from the application, though (or provide some other way of determining the version). You can even put the version information into a different file (it could be stored inside the archive holding the resources, for example).
Again, it is your choice how strict you want to handle everything, and how easy or complicated it should be.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

vongodric

  • Guest
Re: Hi
« Reply #6 on: February 04, 2006, 02:18:00 am »
I think plugin identification is just a matter of design and there are many ways to do it. I think the easier it is to write plugins the better, it wouldn't do to have to write some 50+ lines for just to initalise.

More important to me at the moment is to settle down the interface how plugin interacts with the main program. I guess I have whole wx api and provide way to get references to wxApp and wxFrame that are used by the main program. But also probably create an internal IDE interface that is exposed to the plugin. Like access to documentManager, configManager, compilerManager, uiManager( menus, toolbars... ) and etc. This is where the complexity kicks in and where I want things clearified for myself.

  • How to handle events? - I guess on request to connect to main app event handlers. also internal interface can be used to send / receave events.
  • Should plugins be able to interact with eachother? -I don't know if code::block allows that. In some cases it could be even usuable. ( for example code formating plugin interacts with code indenter plugin. to produce output. But in this case they can be the same of course, but it's just an example ). If they do interact then this adds a layer of dependency to the whole system.

Does code::block has any security/protection mechanisms against malicious plugins?

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Hi
« Reply #7 on: February 04, 2006, 06:17:54 pm »
Quote
More important to me at the moment is to settle down the interface how plugin interacts with the main program.
Providing plugin functionality can (again) be done in a hundred ways. One possible way is to call a function like PluginAction() whenever a specific action is wanted from a plugin. Another solution is to use events. You can either send out dedicated events to a plugin, or you can propagate user events (like key strokes and menu events) to the plugins (or a subset) and let them decide... everything is possible.
Both ways are OK, everything works just as well (events are somewhat more expensive, but more flexible).
You derived your plugin from wxEvtHandler. This suggests that you intended to use events.

Quote
But also probably create an internal IDE interface that is exposed to the plugin. Like access to documentManager, configManager, compilerManager, uiManager( menus, toolbars... ) and etc.
A manager is usually a singleton class and thus you need no special interface to access it from the plugin.

Quote
How to handle events? - I guess on request to connect to main app event handlers.
An event table is the easiest way, since you know what events the plugin will be wanting in advance.

Quote
Should plugins be able to interact with eachother?
This is your decision. To me, it makes little sense, as such dependencies bring a *lot* of troubles, but it is very easy to provide that functionality (just offer a function that enumerates all plugins with pointers to their Get() function).

Quote
Does code::block has any security/protection mechanisms against malicious plugins?
Yes, we look at the sources :)
Other than that, you cannot protect yourself from malicious plugins.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

vongodric

  • Guest
Re: Hi
« Reply #8 on: February 04, 2006, 07:21:01 pm »
Thanks Thomas you'v been a great help  :)