Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

Pure Python Plugins, general DLL

Help
2011-05-10
2013-11-24
  • Jari Pennanen
    Jari Pennanen
    2011-05-10

    Hi!

    I've skimmed & compiled thru examples and I decided I need to make own plugin. Though I was a disappointed to know that I needed to dive C/C++ to do it.

    Questions first, is there a way to determine when Python Script is initialized in C++, e.g. in beNotified, (see 2. from below)?

    Anyways I've come up a general plugin DLL idea for "pure" Python plugins:

    1. Use DLL filename as basis for python script. (Using GetModuleFilename()).
    2. On Python Script initialization it should add this python script dir to python path.
    3. Get FuncItem list for the Python Plugin from INI(*) file, that defines (name, python exec statement, hotkey)

    This way one can have one DLL file to create any kind of Python plugins for n++.

    * We cannot access python during getFuncsArray so this must be stored in INI file or someplace else.

     
  • Firstly, you don't need to write a plugin in C/C++ - any language that can export DLL entry points will do, Delphi, Oberon, Pascal have all been used to write plugins.  There's a .NET template too.

    The general plugin idea is a great one - I though of doing something similar for the Zen Coding plugin, as really that's all it is - never got round to it though, and it looks like you've thought through it far more than I did!  You might want to allow some "initialisation" python in the .ini (or maybe .xml?) too.  XML might be much easier, as embedding python in .XML is easier than an ini (imagine if you need a multi-line statement in an ini vs in XML).

    You can't actually tell (at the moment) when Python is initialised, but you can always send a NPPM_MSGTOPLUGIN to Python Script - if it's not already initialised, it will initialise itself when it receives the first message.  If this causes issues, or you need something in the plugin itself, then feel free to shout.

    A switch for the "plugin" ini/xml whether it needs to initialise itself (i.e. add the path to sys.path and run the initialisation Python) upon Notepad++ startup or when the first function from the plugin is used could be useful - Zen Coding for instance, only needs to run the initial code when the first menu option is selected, however something that sends some initialisation commands to Scintilla would need to be run at startup.

    One last point, is that if the actual DLL source could be available, then people can recompile it with something changed, so it gets a different version and different MD5 - then plugin manager can handle version upgrades (which without that option may upgrade everything apart from the actual DLL, which Plugin manager can't deal with).

    Sounds like a great idea, and I'm sure many many python-like plugins could be created with it.  If you need anything, just shout.

    Cheers,
    Dave.

     
  • Jari Pennanen
    Jari Pennanen
    2011-05-11

    Hi!

    Thanks for your reply!

    Did it already, see _NppyPluginDll_ it is in GitHub and I placed it to public domain.

    I happened to do it already so I'm not planning to change it to XML at least not yet. It works with INI files so easily, I don't see any purpose to have multiline statements in the "manifesto" INI, since multiple lines can be in own module functions.

    Copy all the data from Example/ directory to plugin dir and it should work.

    Waiting for feedback!

     
  • Jari Pennanen
    Jari Pennanen
    2011-05-11

    One last point, is that if the actual DLL source could be available, then people can recompile it with something changed, so it gets a different version and different MD5 - then plugin manager can handle version upgrades (which without that option may upgrade everything apart from the actual DLL, which Plugin manager can't deal with).

    Can I add just some dummy string to DLL file that user can manually change with hex-editor? Compiling is the major PITA when one is accustomed to Python.

     
  • Can I add just some dummy string to DLL file that user can manually change with hex-editor?

    Yes. :)

    I'll try to take a look at it tomorrow - great news it's done already.

     
  • Jari Pennanen
    Jari Pennanen
    2011-05-12

    You can't actually tell (at the moment) when Python is initialised, but you can always send a NPPM_MSGTOPLUGIN to Python Script - if it's not already initialised, it will initialise itself when it receives the first message.  If this causes issues, or you need something in the plugin itself, then feel free to shout.

    Ah here is my problem, if I try to call python during "NPPN_READY" it always fails, this is probably because Python Script inits itself during NPPN_READY too, so I need to hook my startup scripts *after* PythonScript NPPN_READY. Can I do this without kludgy timers?

     
  • Jari Pennanen
    Jari Pennanen
    2011-05-12

    I now did the startup switch called "initonstartup" so you may try out the error easily:

    Open up the NppyPluginExample.ini, and set the initonstartup=1 - now from C++ the code you can see it tries to call it upon NPPN_READY:

            case NPPN_READY:
                if (pluginInitOnStartup) {
                    PYINITLAZY();
                }
                break;
    

    and this fails with Unknown exception

     
  • Jari Pennanen
    Jari Pennanen
    2011-05-12

    Ah one workaround is to name all the python plugins so that they are in alphabet after the PythonScript.dll:

    If my python plugin is inited after PythonScript.dll it works, e.g. if I name the NppyPluginExample as PZPluginExample it works… This might not be such a bad idea, but it might be confusing for end users.

    Other ideas?

     
  • Other ideas?

    Yeah, we'll fix it :)

    Just taken a look, and it looks like it's the non-Python initialisation that isn't complete if you fire a MSGTOPLUGIN before Python Script has had it's NPPN_READY.  When I get 10 minutes, I'll see if I can check for that in the MSGTOPLUGIN, and do the necessary initialisation then.

    So, for now, keep the order correct with the DLL naming  hack, and I'll post a fix shortly.

    Cheers,

    Dave.

     
  • Jari Pennanen
    Jari Pennanen
    2011-05-16

    I've studied the part that is "non-Python" initialization namely PythonScript.cpp initialise() function, I've come to conclusion that it can be safely moved to first line of initialisePython. Though can't confirm since I hate compiling (and hunting dependencies!) under Windows.

    Anyways only side-effect is that it must NOT be called before NPPN_READY of some plugin. Earliest one can initialise the console etc. is in any NPPN_READY, it should not matter if the caller was named 111.DLL (before PythonScript.dll) or ZZZ.dll (after PythonScript.dll) as long as it's MSGTOPLUGIN is earliest at plugin's NPPN_READY.

    Thanks.

     


  • 2011-06-10

    Ciantic,
    I've studied your code. I am not great at C/C++, but I can muddle through it if I absolutely have to. And, believe me, I take great pains to not have to.
    I have to ask, what is the added value to me as a developer in using this plugin?
    What can I accomplish by using the plugin that I cannot accomplish by writing a suitable Npp-aware Python script, and using it in PythonScript directly?
    Am I missing something here?
    Thanks,
    Dave W.
    (Not to be confused with DaveGB. By a long shot. ;-)

     


  • 2011-06-12

    Ok, I see it now. If I have a long script with a lot of functions, I could split them out into separate menu entries this way, like the TextFX submenus do, and still have them all in one module for easier maintenance. Yes, that would be handy.

     
    • Jari Pennanen
      Jari Pennanen
      2013-11-24

      I know this is old one, but since I need this plugin once again, I decided to comment.

      Reason is exactly that, splitting the functions in plugin to menu entries. And when they are in menu entries one can assign keyboard shortcuts to each function using native Notepad++ options dialog. This is not possible with scripts.