Through the Interface: Jigging an AutoCAD solid using IronRuby and .NET (well, almost)

May 2015

Sun Mon Tue Wed Thu Fri Sat
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30


« Using IronRuby with AutoCAD | Main | Customizing the display of standard AutoCAD objects using .NET »

April 06, 2009

Jigging an AutoCAD solid using IronRuby and .NET (well, almost)

In the last post I introduced a very simple “Hello World!” IronRuby application working with AutoCAD, just as I’d previously done with IronPython. My idea for this post was to take the code from my second IronPython post – which showed how to jig an AutoCAD solid from IronPython – and get it working with IronRuby, forcing me to learn a little more Ruby in the process.

All started out well: to convert the basic syntax from Python to Ruby was straightforward, and I have a definite liking for the syntax of the Ruby language. Especially when working with object orientation: the code for implementing classes feels cleaner than Python and it’s really OO from top to bottom (everything’s an object). I even found a way to avoid all those namespaces everywhere in the code – you just assign them to symbols and use those intead.

So what didn’t work? Well, it turns out there’s a problem with the definition of the EntityJig class, which is the parent of our SolidJig: IronRuby tells me it doesn’t have a default constructor defined. It’s very similar in nature to the problem I had deriving the IronPython version of my SolidJig class, but in this case I had to make sure my code very specifically implemented an __init__ function taking an entity (IronRuby uses initialize() instead of __init__ and is really clean in the way it allows you to super-message to your parent class, but right now it seems there’s something getting in the way – IronRuby is at version 0.3, after all).

Here’s my IronRuby script – for the RBLOAD command look at the C# code in the last post.

require 'C:\Program Files\Autodesk\AutoCAD 2009\acmgd.dll'

require 'C:\Program Files\Autodesk\AutoCAD 2009\acdbmgd.dll'

require 'C:\Program Files\Autodesk\AutoCAD 2009\acmgdinternal.dll'


Ai =  Autodesk::AutoCAD::Internal

Aiu = Autodesk::AutoCAD::Internal::Utils

Aas = Autodesk::AutoCAD::ApplicationServices

Ads = Autodesk::AutoCAD::DatabaseServices

Aei = Autodesk::AutoCAD::EditorInput

Ag =  Autodesk::AutoCAD::Geometry

Ar =  Autodesk::AutoCAD::Runtime


def print_message(msg)

  app = Aas::Application

  doc = app.DocumentManager.MdiActiveDocument

  ed = doc.Editor




# Function to register AutoCAD commands


def autocad_command(cmd) 

  cc = method(cmd)

  Aiu.AddCommand('rbcmds', cmd, cmd, Ar::CommandFlags.Modal, cc)


  # Let's now write a message to the command-line


  print_message("\nRegistered Ruby command: " + cmd)



def add_commands(names)

  names.each { |n| autocad_command n }



# Let's do something a little more complex...


class SolidJig < Aei::EntityJig


  # Initialization function


  def initialize(ent)


    # Call the base class and store the object



    @sol = ent




  # The function called to run the jig


  def StartJig(ed, pt)


    # The start point is specified outside the jig


    @start = pt

    @end = pt


    return ed.Drag(self)



  # The sampler function


  def Sampler(prompts)


    # Set up our selection options


    jo =

    jo.UserInputControls = (

      Aei::UserInputControls.Accept3dCoordinates |

      Aei::UserInputControls.NoZeroResponseAccepted |


    jo.Message = "\nSelect end point: "     


    # Get the end point of our box


    res = prompts.AcquirePoint(jo)


    if @end == res.Value

      return Aei::SamplerStatus.NoChange


      @end = res.Value



    return Aei::SamplerStatus.OK



  # The update function


  def Update()


    # Recreate our Solid3d box




      # Get the width (x) and depth (y)


      x = @end.X - @start.X

      y = @end.Y - @start.Y


      # We need a non-zero Z value, so we copy Y


      z = y


      # Create our box and move it to the right place





            @start.X + x/2,

            @start.Y + y/2,

            @start.Z + z/2)))


      return false


    return true




# Create a box using a jig


def boxjig


  app = Aas::Application

  doc = app.DocumentManager.MdiActiveDocument

  db = doc.Database

  ed = doc.Editor


  # Select the start point before entering the jig


  ppr = ed.GetPoint("\nSelect start point: ")


  if ppr.Status == Aei::PromptStatus.OK


    # We'll add our solid to the modelspace


    tr = doc.TransactionManager.StartTransaction

    bt =




    btr =



    # Make sure we're recording history to allow grip editing


    sol =

    sol.RecordHistory = true


    # Now we add our solid



    tr.AddNewlyCreatedDBObject(sol, true)


    # And call the jig before finishing




      sj = sol


      ppr2 = sj.StartJig(ed, ppr.Value)


      # Only commit if all completed well


      if ppr2.Status == Aei::PromptStatus.OK






      print_message("\nProblem found: " + $! + "\n")








add_commands ["boxjig"]

When we run the RBLOAD command and select this script, our BOXJIG command gets defined.

Registered Ruby command: boxjig

When this is run, our Begin-Rescue block (equivalent to Try-Catch in most other modern programming languages :-) catches the exception and prints an error statement at the command-line:

Command: BOXJIG

Select start point:

Problem found: Parent does not have a default constructor. The default constructor must be explicitly defined.

I’m hoping the root cause of the issue is obvious to someone familiar with IronRuby, whether in the above calling code, the design of the API exposed by AutoCAD or the implementation of IronRuby itself.

I do prefer not to post code that doesn’t actually work, but I feel there’s still value in seeing the comparison between the Python and Ruby scripts, for people to get a feel for how the languages differ. And - apart from anything else – I’ve hit my head against this for long enough that I at least want to get a post out of it. :-)


Ivan Porto Carrero – who’s working on the book IronRuby in Action – is able to reproduce the issue outside of AutoCAD and has offered to log a bug. Hopefully it’ll get addressed in a future build of IronRuby (or someone will spell out how I can handle it cleanly from my side).


TrackBack URL for this entry:

Listed below are links to weblogs that reference Jigging an AutoCAD solid using IronRuby and .NET (well, almost):

blog comments powered by Disqus


10 Random Posts