diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc
index 9232b78ea..15d0d5c12 100644
--- a/src/db/db/dbLayoutToNetlist.cc
+++ b/src/db/db/dbLayoutToNetlist.cc
@@ -284,7 +284,7 @@ void LayoutToNetlist::connect_impl (const db::ShapeCollection &a, const db::Shap
m_conn.connect (dla.layer (), dlb.layer ());
}
-void LayoutToNetlist::connect_global_impl (const db::ShapeCollection &l, const std::string &gn)
+size_t LayoutToNetlist::connect_global_impl (const db::ShapeCollection &l, const std::string &gn)
{
if (m_netlist_extracted) {
throw tl::Exception (tl::to_string (tr ("The netlist has already been extracted")));
@@ -297,7 +297,7 @@ void LayoutToNetlist::connect_global_impl (const db::ShapeCollection &l, const s
db::DeepLayer dl = deep_layer_of (l);
m_dlrefs.insert (dl);
- m_conn.connect_global (dl.layer (), gn);
+ return m_conn.connect_global (dl.layer (), gn);
}
const std::string &LayoutToNetlist::global_net_name (size_t id) const
diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h
index 4d103e66e..a7875863c 100644
--- a/src/db/db/dbLayoutToNetlist.h
+++ b/src/db/db/dbLayoutToNetlist.h
@@ -398,18 +398,18 @@ public:
* @brief Connects the given layer with a global net with the given name
* Returns the global net ID
*/
- void connect_global (const db::Region &l, const std::string &gn)
+ size_t connect_global (const db::Region &l, const std::string &gn)
{
- connect_global_impl (l, gn);
+ return connect_global_impl (l, gn);
}
/**
* @brief Connects the given text layer with a global net with the given name
* Returns the global net ID
*/
- void connect_global (const db::Texts &l, const std::string &gn)
+ size_t connect_global (const db::Texts &l, const std::string &gn)
{
- connect_global_impl (l, gn);
+ return connect_global_impl (l, gn);
}
/**
@@ -872,7 +872,7 @@ private:
db::properties_id_type make_netname_propid (db::Layout &ly, const tl::Variant &netname_prop, const db::Net &net) const;
db::CellMapping make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector *nets, bool with_device_cells);
void connect_impl (const db::ShapeCollection &a, const db::ShapeCollection &b);
- void connect_global_impl (const db::ShapeCollection &l, const std::string &gn);
+ size_t connect_global_impl (const db::ShapeCollection &l, const std::string &gn);
// implementation of NetlistManipulationCallbacks
virtual size_t link_net_to_parent_circuit (const Net *subcircuit_net, Circuit *parent_circuit, const DCplxTrans &trans);
diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc
index cedc464ab..1f46e9139 100644
--- a/src/db/db/gsiDeclDbLayoutToNetlist.cc
+++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc
@@ -357,12 +357,12 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"\n"
"This variant has been introduced in version 0.27.\n"
) +
- gsi::method ("connect_global", (void (db::LayoutToNetlist::*) (const db::Region &, const std::string &)) &db::LayoutToNetlist::connect_global, gsi::arg ("l"), gsi::arg ("global_net_name"),
+ gsi::method ("connect_global", (size_t (db::LayoutToNetlist::*) (const db::Region &, const std::string &)) &db::LayoutToNetlist::connect_global, gsi::arg ("l"), gsi::arg ("global_net_name"),
"@brief Defines a connection of the given layer with a global net.\n"
"This method returns the ID of the global net. Use \\global_net_name to get "
"the name back from the ID."
) +
- gsi::method ("connect_global", (void (db::LayoutToNetlist::*) (const db::Texts &, const std::string &)) &db::LayoutToNetlist::connect_global, gsi::arg ("l"), gsi::arg ("global_net_name"),
+ gsi::method ("connect_global", (size_t (db::LayoutToNetlist::*) (const db::Texts &, const std::string &)) &db::LayoutToNetlist::connect_global, gsi::arg ("l"), gsi::arg ("global_net_name"),
"@brief Defines a connection of the given text layer with a global net.\n"
"This method returns the ID of the global net. Use \\global_net_name to get "
"the name back from the ID."
diff --git a/src/lay/lay/doc/programming/ruby_binding.xml b/src/lay/lay/doc/programming/ruby_binding.xml
index b79241c2a..7449de54a 100644
--- a/src/lay/lay/doc/programming/ruby_binding.xml
+++ b/src/lay/lay/doc/programming/ruby_binding.xml
@@ -278,6 +278,29 @@ event._manage
and pointers/references and also supports "out" parameters.
+ "void" as return value
+
+
+ While a "void" return value indicates "no return value" in C++, this concept is not
+ common in Ruby. Ruby methods will always return the last value generated in
+ a method.
+
+
+
+ For consistency, KLayout's Ruby binding returns "self" from methods in this
+ case. This allows chaining of methods in many cases and fosters compact code:
+
+
+ // C++
+class A {
+public:
+ virtual void f() { ... }
+ virtual void g() { ... }
+};
+
+# Ruby
+a = A::new.f.g
+
References and pointers to simple types (FixNum, Float, String)
diff --git a/src/rba/rba/rba.cc b/src/rba/rba/rba.cc
index d7e9a1091..3ee9dd964 100644
--- a/src/rba/rba/rba.cc
+++ b/src/rba/rba/rba.cc
@@ -887,6 +887,15 @@ method_name_from_id (int mid, VALUE self)
return cls_decl->name () + "::" + mt->name (mid);
}
+static gsi::ArgType create_void_type ()
+{
+ gsi::ArgType at;
+ at.init ();
+ return at;
+}
+
+static gsi::ArgType s_void_type = create_void_type ();
+
VALUE
method_adaptor (int mid, int argc, VALUE *argv, VALUE self, bool ctor)
{
@@ -1077,8 +1086,15 @@ method_adaptor (int mid, int argc, VALUE *argv, VALUE self, bool ctor)
}
+ } else if (meth->ret_type () == s_void_type) {
+
+ // simple, yet magical :)
+ return self;
+
} else {
+
ret = pop_arg (meth->ret_type (), p, retlist, heap);
+
}
}
diff --git a/testdata/ruby/dbPolygonTest.rb b/testdata/ruby/dbPolygonTest.rb
index 73c592830..02602f61c 100644
--- a/testdata/ruby/dbPolygonTest.rb
+++ b/testdata/ruby/dbPolygonTest.rb
@@ -777,6 +777,19 @@ class DBPolygon_TestClass < TestBase
end
+ def test_voidMethodsReturnSelf
+
+ hull = [ RBA::Point::new(0, 0), RBA::Point::new(6000, 0),
+ RBA::Point::new(6000, 3000), RBA::Point::new(0, 3000) ]
+ hole1 = [ RBA::Point::new(1000, 1000), RBA::Point::new(2000, 1000),
+ RBA::Point::new(2000, 2000), RBA::Point::new(1000, 2000) ]
+ hole2 = [ RBA::Point::new(3000, 1000), RBA::Point::new(4000, 1000),
+ RBA::Point::new(4000, 2000), RBA::Point::new(3000, 2000) ]
+ poly = RBA::Polygon::new(hull).insert_hole(hole1).insert_hole(hole2)
+ assert_equal(poly.to_s, "(0,0;0,3000;6000,3000;6000,0/1000,1000;2000,1000;2000,2000;1000,2000/3000,1000;4000,1000;4000,2000;3000,2000)")
+
+ end
+
end
load("test_epilogue.rb")