Plugin callback context

2006-09-02
2012-11-14
  • Hi Guys

    I'm busy creating a plugin that loads a python script and then exposes the python functions that it finds inside as plugin items.

    It is working quite well at the moment.
    I however have a problem that goes as follows: The callback functions gets no parameters or context as to which FuncItem it belongs to. I have one C function which does the python function call. But when the C plugin function gets called it does not know which python function to call.

    In other words:
    I have 2 python functions A and B.
    I register a FuncItem array of size 2 with the names of function A and B as the plugin item names. Each of these plugin items call the same C function.
    When item A is clicked in NPP the C callback function does not know which python function to call.

    Short of creating a bunch of C functions that look practically the same I don't know to solve this problem. Considered copying the actual memory position of the code but run time code gen turns ugly real quickly.

    Any help would be appreciated.

    Thanx
    Caz

     
    • Don HO
      Don HO
      2006-09-02

      Here's a snip of codes of NppInsertPlugin which is similar the situation you've got :

      funcItem[0]._pFunc = insertCurrentFullPath;
      funcItem[1]._pFunc = insertCurrentFileName;
      funcItem[2]._pFunc = insertCurrentDirectory;

               
      void insertCurrentFullPath()
      {
          insertCurrentPath(FULL_CURRENT_PATH);
      }
      void insertCurrentFileName()
      {
          insertCurrentPath(FILE_NAME);
      }
      void insertCurrentDirectory()
      {
          insertCurrentPath(CURRENT_DIRECTORY);
      }

      void insertCurrentPath(int which)
      {
          int msg = WM_GET_FULLCURRENTPATH;
          if (which == FILE_NAME)
              msg = WM_GET_FILENAME;
          else if (which == CURRENT_DIRECTORY)
              msg = WM_GET_CURRENTDIRECTORY;

          int currentEdit;
          char path[260];
          ::SendMessage(nppData._nppHandle, WM_GETCURRENTSCINTILLA, 0, (LPARAM)&currentEdit);
          ::SendMessage(nppData._nppHandle, msg, 0, (LPARAM)path);
          ::SendMessage(getCurrentHScintilla(currentEdit), SCI_REPLACESEL, 0, (LPARAM)path);
      }

      Hope it helps.

      Don

       
    • Thanx Don

      Doing that would force the plugin to know how many functions there are in the python file beforehand. The number of functions in the python file, however is dynamic. The C plugin must not know anything about the python file it is exposing to NPP.

      So in one case the python script has 2 functions and in another case it has 5. I would hate to impose a maximum limit of script functions that i can expose.

      Implementing your suggestion would look something like this:

      FuncItem funcItem[5];
      PyObject *pyFuncs[5];
      void loadPyFuncs(char *scriptFileName)
      {
        ...
        funcItems[0]._pFunc = pythonCallFunc0;
        strcpy(funcItem[0]._itemName, getName(pyFunc));
        pyFuncs[0] = pyFunc;
        ...
      }

      void pythonCallFunc0()
      {
        PyObject *callablePyFunc = pyFuncs[0];
        PyObject_CallFunction(callablePyFunc,0);
      }
      void pythonCallFunc1()
      {
        PyObject *callablePyFunc = pyFuncs[1];
        PyObject_CallFunction(callablePyFunc,0);
      }
      ...
      void pythonCallFunc4()
      {
        PyObject *callablePyFunc = pyFuncs[4];
        PyObject_CallFunction(callablePyFunc,0);
      }

      I'm trying to write a plugin which simply acts as a bridge between NPP and being able to write python plugins quick and easy. (I love python :)

      An interface that would work for me would have a context void * in funcItems. This context then gets passed into my function:

      void loadPyFuncs(char *scriptFileName)
      {
        ...
        funcItems[i]._pFunc = pythonCallFunc;
        strcpy(funcItem[i]._itemName, getName(pyFunc));
        funcItem[i].context = (void*)pyFunc;
        ...
      }

      void pythonCallFunc(void *context)
      {
        PyObject *callablePyFunc = (PyObject*)context;
        PyObject_CallFunction(callablePyFunc,0);
      }

      Which allows me to simply have 1 function to service as many python functions as there are in the script.

      Any ideas on how i can do something similar?
      Thanx, Caz