class RbPlusPlus::Builders::Base

Base class for all code generation nodes

A Node is simply a handler for one complete statement or block of C++ code.

The code generation system for Rb++ is a two step process. We first, starting with an ExtensionNode, build up an internal representation of the resulting code, setting up all the code nodes required for proper wrapping of the library.

Once that’s in place, then we run through the tree, actually generating the C++ wrapper code.



Link to the underlying rbgccxml node this node is writing code for


List of declaration nodes for this node


List of children nodes that generate code that the entire extension needs to be able to read. Code that fits here includes any auto-generated to_/from_ruby and any Allocation Strategies


List of includes for this node


List of children nodes


Link to the parent node of this node


List of registeration nodes for this node


The Rice variable name for this node


The type of the #rice_variable

Public Class Methods

new(code, parent = nil) click to toggle source
# File lib/rbplusplus/builders/base.rb, line 46
def initialize(code, parent = nil)
  @code = code
  @parent = parent
  @includes = []
  @declarations = []
  @registrations = []
  @nodes = []
  @global_nodes = []

Public Instance Methods

build() click to toggle source

Trigger the construction of the internal representation of a given node. All nodes must implement this.

# File lib/rbplusplus/builders/base.rb, line 63
def build
  raise "Nodes must implement #build"
has_children?() click to toggle source

Does this builder node have child nodes?

# File lib/rbplusplus/builders/base.rb, line 57
def has_children?
  @nodes && !@nodes.empty?
qualified_name() click to toggle source

Proxy method for writers

# File lib/rbplusplus/builders/base.rb, line 97
def qualified_name
sort() click to toggle source

Once building is done, the resulting node tree needs to be sorted according to subclass / superclass definitions. Like anything with C++, Rice needs to know about base classes before it can build sub classes. We go through each node’s children, sorting them according to this.

# File lib/rbplusplus/builders/base.rb, line 77
def sort
  @nodes.each { |n| n.sort }

  # sort_by lets us build an array of numbers that Ruby then uses
  # to sort the list. Our method here is to simply specify the
  # depth a given class is in a heirarchy, as bigger numbers end
  # up sorted farther down the list
  @nodes =
    @nodes.sort_by do |a|
      if a.is_a?(ClassNode)
      elsif a.is_a?(ImplicitCasterNode) # Hmm, hack
write() click to toggle source

After build has run, this then triggers the actual generation of the C++ code All nodes must implement this.

# File lib/rbplusplus/builders/base.rb, line 69
def write
  raise "Nodes must implement #write"

Protected Instance Methods

add_child(node) click to toggle source

Given a new node, build it and add it to our nodes list

# File lib/rbplusplus/builders/base.rb, line 124
def add_child(node)
  nodes << node
add_global_child(node) click to toggle source

Add a node to the “globals” list. See the declaration of #global_nodes

# File lib/rbplusplus/builders/base.rb, line 130
def add_global_child(node)
  global_nodes << node
do_not_wrap?(node) click to toggle source

Should this node be wrapped as it is or has the user specified something else for this node?

# File lib/rbplusplus/builders/base.rb, line 115
def do_not_wrap?(node)
  node.ignored? ||
    (node.moved_to && node.moved_to != self.code) ||
    !node.public? ||
    (node.is_a?(RbGCCXML::Struct) && node.incomplete?) ||
find_typedef(node = self.code) click to toggle source

Any node can also have a typedef. There are cases where it’s much better to use a typedef instead of the original fully qualified name, for example deep template definitions (say, any STL structures). This method will look for the best Typedef to use for this node. This lookup can be disabled on a per-node basis by calling node.disable_typedef_lookup, as there are cases where the typedef search works against the parsed code.

@returns the typedef node found or the node passed in (self.code by default)

# File lib/rbplusplus/builders/base.rb, line 143
def find_typedef(node = self.code)
  return node if node.is_a?(RbGCCXML::FundamentalType)

  found = last_found = node

  if !node._disable_typedef_lookup?
    while found
      last_found = found
      typedef = RbGCCXML::NodeCache.all("Typedef").select {|t| t.attributes["type"] == found.attributes["id"]}.first

      # Some typedefs have the access attribute, some don't. We want those without the attribute
      # and those with the access="public". For this reason, we can't put :access => "public" in the
      # query above.
      found = (typedef && typedef.public?) ? typedef : nil

  if node == self.code && last_found != node
    Logger.debug "Found Typedef #{last_found.qualified_name} for #{node.qualified_name}"

Also aliased as: find_typedef_for
find_typedef_for(node = self.code) click to toggle source
Alias for: find_typedef
superclass_count(node) click to toggle source

Count the heirarchy depth of a given class node

# File lib/rbplusplus/builders/base.rb, line 104
def superclass_count(node)
  count = 0
  n = node
  while n = n.superclass
    count += 1