return ((char *)obj - vt->_base + chain->off_ichain);
}
+/* --- @sod_init@, @sod_initv@ --- *
+ *
+ * Arguments: @const SodClass *cls@ = class object for new instance
+ * @void *p@ = pointer to storage for new instance
+ * @va_list ap, ...@ = initialization keyword arguments
+ *
+ * Returns: Pointer to the initialized instance.
+ *
+ * Use: Initializes an instance in pre-allocated storage, and returns
+ * a pointer to it.
+ *
+ * This function will imprint the storage, and then send an
+ * `initialize' message to the fresh instance containing the
+ * provided keyword arguments.
+ *
+ * It's usually convenient to use the macro @SOD_INIT@ rather
+ * than calling @sod_init@ directly.
+ */
+
+void *sod_init(const SodClass *cls, void *p, ...)
+{
+ va_list ap;
+
+ va_start(ap, p);
+ sod_initv(cls, p, ap);
+ va_end(ap);
+ return (p);
+}
+
+void *sod_initv(const SodClass *cls, void *p, va_list ap)
+{
+ SodObject *obj;
+
+ cls->cls.imprint(p);
+ obj = SOD_CONVERT(SodObject, p);
+ SodObject_init__v(obj, ap);
+ return (p);
+}
+
+/* --- @sod_teardown@ --- *
+ *
+ * Arguments: @void *p@ = pointer to an instance to be torn down
+ *
+ * Returns: Zero if the object is torn down; nonzero if it refused for
+ * some reason.
+ *
+ * Use: Invokes the instance's `teardown' method to release any held
+ * resources.
+ *
+ * If this function returns nonzero, then the object is still
+ * active, and may still hold important resources. This is not
+ * intended to be a failure condition: failures in teardown are
+ * usually unrecoverable (or very hard to recover from) and
+ * should probably cause the program to abort. A refusal, on
+ * the other hand, means that the object is still live and
+ * shouldn't be deallocated, but that this is a normal situation
+ * and the caller shouldn't worry about it.
+ */
+
+int sod_teardown(void *p)
+{
+ SodObject *obj;
+
+ obj = SOD_CONVERT(SodObject, p);
+ return (SodObject_teardown(obj));
+}
+
/*----- That's all, folks -------------------------------------------------*/