Python script with PluginFactory

edited December 2017 in Python scripting

Dear experts

I am trying to reproduce the Ruby script example for PluginFactory from here https://www.klayout.de/doc/code/class_PluginFactory.html

class PluginTestFactory < RBA::PluginFactory

  # Constructor
  def initialize
    # registers the new plugin class at position 100000 (at the end), with name
    # "my_plugin_test" and title "My plugin test"
    register(100000, "my_plugin_test", "My plugin test")
  end

  # Create a new plugin instance of the custom type
  def create_plugin(manager, main_window, view)
    return PluginTest.new
  end

end

# The plugin class
class PluginTest < RBA::Plugin
  def mouse_moved_event(p, buttons, prio)
    if prio
      # Set the cursor to cross if our plugin is active.
      set_cursor(RBA::Cursor::Cross)
    end
    # Returning false indicates that we don't want to consume the event.
    # This way for example the cursor position tracker still works.
    false
  end
  def mouse_click_event(p, buttons, prio)
    if prio
      puts "mouse button clicked."
      # This indicates we want to consume the event and others don't receive the mouse click
      # with prio = false.
      return true
    end
    # don't consume the event if we are not active.
    false
  end
end

# Instantiate the new plugin factory.
PluginTestFactory.new

This is what I have so far:

class PluginTestFactory(pya.PluginFactory):
    def __init__(self):
        super().__init__()
        self.register(100000, 'my_plugin_test', 'My plugin test')

    def create_plugin(self, manager, root, view):
        return PluginTest()

class PluginTest(pya.Plugin):
    def __init__(self):
        super().__init__()

    def mouse_moved_event(self, p, buttons, prio):
        if prio:
            self.set_cursor(pya.Cursor.Cross)
        return False

    def mouse_click_event(self, p, buttons, prio):
        if prio:
            print('this output goes in the terminal')
            return True
        return False

PluginTestFactory()

However, if I

  1. open a gds file with two boxes (this one, specifically: https://www.dropbox.com/s/j11zhnjxszta3iq/foo_static.GDS?dl=0)

  2. Run the script from the Macro Development dialog in debug mode with Shift+F5

I get the error

Caught the following exception:
std:bad_alloc in PluginFactory.register (Class RuntimeError)

>

Press 'Ok' to continue and 'Cancel' to stop in the debugger

On clicking 'Ok' I get the following:

std::bad_alloc in PluginFactory.register

C:/Users/MCHels/KLayout/pymacros/qt_designer_python_1.lym:4

C:/Users/MCHels/KLayout/pymacros/qt_designer_python_1.lym:24

So, did I mess up the Ruby to Python conversion or is something else up?

Also, thanks to Matthias for creating this awesome piece of software!

Comments

  • edited November -1

    Hi,

    thanks for reporting this issue.

    I can reproduce the problem. Apparently it's a reference count issue with the object returned by create_plugin. With Ruby there is no such issue because Ruby does memory management differently.

    A workaround is to hold a reference to the new object

    class PluginTestFactory(pya.PluginFactory):
        plugins = []
    
        def __init__(self):
            super(PluginTestFactory, self).__init__()
            self.register(100000, 'my_plugin_test', 'My plugin test')
    
        def create_plugin(self, manager, root, view):
            p = PluginTest()
            PluginTestFactory.plugins.append(p)
            return p
    

    However, this creates a memory leak because those objects are never deleted.

    I'll take a look into this.

    Regards,

    Matthias

  • edited November -1

    Hi Matthias

    Thank you for getting back to me on this. You're awesome.

    Cheers,
    Morten

Sign In or Register to comment.