+#include <yaz/xmalloc.h>
+
+/* Used by the *_setl() functions */
+typedef char opaquechar;
+
+/* Used as the return value of the *_getl() functions */
+struct datachunk {
+ char *data;
+ int len;
+};
+
+/* Used to package Perl function-pointer and user-data together */
+struct callback_block {
+ SV *function;
+ SV *handle;
+};
+
+/* The callback function used for ZOOM_options_set_callback(). I do
+ * not claim to fully understand all the stack-hacking magic, and less
+ * still the reference-counting/mortality stuff. Accordingly, the
+ * memory management here is best characterised as What I Could Get To
+ * Work, More Or Less.
+ */
+const char *__ZOOM_option_callback (void *handle, const char *name)
+{
+ struct callback_block *cb = (struct callback_block*) handle;
+ int count;
+ SV *ret;
+ char *s;
+ char *res;
+
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ XPUSHs(cb->handle);
+ XPUSHs(sv_2mortal(newSVpv(name, 0)));
+ PUTBACK;
+ /* Perl_sv_dump(0, cb->function); */
+
+ count = call_sv(cb->function, G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1)
+ croak("callback function for ZOOM_options_get() returned %d values: should have returned exactly one", count);
+
+ ret = POPs;
+ if (SvPOK(ret)) {
+ s = SvPV_nolen(ret);
+ /* ### `res' never gets freed! I think it is
+ * impossible to solve this problem "correctly"
+ * because the ZOOM-C option callback interface is
+ * inadequate. */
+ res = xstrdup(s);
+ } else {
+ res = 0;
+ }
+
+ PUTBACK;
+ FREETMPS;
+ LEAVE;
+
+ return res;
+}
+
+
+MODULE = Net::Z3950::ZOOM PACKAGE = Net::Z3950::ZOOM PREFIX=ZOOM_