diff --git a/src/builtin.cmod b/src/builtin.cmod
index f7c94588a7534dbd2267b309e572836f1a3647b3..9ad0711571f3911c2e6d62604caa7f691459118c 100644
--- a/src/builtin.cmod
+++ b/src/builtin.cmod
@@ -3605,6 +3605,79 @@ PMOD_EXPORT void append_list_node(struct pike_list_node *node,
 /*! @module Builtin
  */
 
+/*! @class Setter
+ *!
+ *! Internal class for implementing setters.
+ */
+PIKECLASS Setter
+{
+  PIKEVAR object o
+    flags ID_PROTECTED|ID_PRIVATE|ID_LOCAL;
+  CVAR int f;
+  PIKEFUN void `()(mixed val)
+    flags ID_PROTECTED;
+  {
+    if (!THIS->o) {
+      Pike_error("Uninitialized Setter!\n");
+    }
+    object_low_set_index(THIS->o, THIS->f, Pike_sp-1);
+    pop_n_elems(args);
+    push_int(0);
+  }
+  PIKEFUN string _sprintf(int c, mapping|void opts)
+    flags ID_PROTECTED;
+  {
+    struct program *prog;
+    if (!THIS->o) {
+      push_constant_text("Setter()");
+    } else if ((prog = THIS->o->prog)) {
+      push_constant_text("%O->`%s=");
+      ref_push_object(THIS->o);
+      ref_push_string(ID_FROM_INT(prog, THIS->f)->name);
+      f_sprintf(3);
+    } else {
+      push_constant_text("Setter(destructed object)");
+    }
+    stack_pop_n_elems_keep_top(args);
+  }
+}
+
+PMOD_EXPORT struct object *get_setter(struct object *o, int f)
+{
+  struct object *res = clone_object(Setter_program, 0);
+  struct Setter_struct *setter = OBJ2_SETTER(res);
+  add_ref(setter->o = o);
+  setter->f = f;
+  return res;
+}
+
+/*! @decl function(mixed_void) _get_setter(object o, string s)
+ *!
+ *! Get a setter for the variable named @[s] in object @[o].
+ *!
+ *! @seealso
+ *!   @[object_variablep()]
+ */
+PIKEFUN function(mixed:void) _get_setter(object o, string s)
+{
+  struct program *p;
+  int f;
+  if (!(p = o->prog)) {
+    Pike_error("Indexing a destructed object.\n");
+  }
+  f = find_shared_string_identifier(s, p);
+  if ((f >= 0) &&
+      IDENTIFIER_IS_VARIABLE(ID_FROM_INT(p, f)->identifier_flags)) {
+    push_function(get_setter(o, f), f_Setter_cq__backtick_28_29_fun_num);
+  } else {
+    push_undefined();
+  }
+  stack_pop_n_elems_keep_top(args);
+}
+
+/*! @endclass
+ */
+
 /*! @class SqlNull
  *!
  *! This class is used to implement the low-level aspects of @[Val.Null].
diff --git a/src/builtin_functions.h b/src/builtin_functions.h
index 9857fe3b49d43971a902d4f64f07bfa7366b11ac..0ee6303c3efb0b74173581d6ea6ea382522eba57 100644
--- a/src/builtin_functions.h
+++ b/src/builtin_functions.h
@@ -215,6 +215,7 @@ PMOD_EXPORT void prepend_list_node(struct pike_list_node *node,
 				   struct pike_list_node *new_node);
 PMOD_EXPORT void append_list_node(struct pike_list_node *node,
 				  struct pike_list_node *new_node);
+PMOD_EXPORT struct object *get_setter(struct object *o, int f);
 void init_builtin(void);
 void exit_builtin(void);