You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2015/08/23 13:17:34 UTC
[3/3] lucy-clownfish git commit: Rework Perl SV to Clownfish object
conversion
Rework Perl SV to Clownfish object conversion
Consolidate the main code paths of the two previous conversion functions
XSBind_sv_to_cfish_obj and XSBind_perl_to_cfish, removing subtle
differences.
One major effect is that hashrefs or arrayrefs passed to Clownfish
functions taking a Clownfish::Obj will now be converted to a Hash or
Vector, not a String.
Only convert unblessed arrayrefs or hashrefs to Vector or Hash.
Non-Clownfish objects will always be stringified.
Remove support for passing AVs or HVs directly. Callers must pass a
arrayref or hashref.
Make XSBind_perl_to_cfish take a Class argument and guarantee that the
returned object is of this class.
Make XSBind_perl_to_cfish throw on undefined SVs. Add
XSBind_perl_to_cfish_nullable that allows undef to NULL conversion.
Rename XSBind_sv_to_cfish_obj to XSBind_perl_to_cfish_noinc.
Remove XSBind_maybe_sv_to_cfish_obj.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/8875d01e
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/8875d01e
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/8875d01e
Branch: refs/heads/master
Commit: 8875d01edb4f77dc95c85f59925389f9a3fc0e10
Parents: 2330790
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Wed Aug 5 20:55:08 2015 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sun Aug 23 13:16:48 2015 +0200
----------------------------------------------------------------------
compiler/src/CFCPerl.c | 3 +-
compiler/src/CFCPerlMethod.c | 2 +-
compiler/src/CFCPerlTypeMap.c | 7 +-
.../perl/buildlib/Clownfish/Build/Binding.pm | 9 +-
runtime/perl/xs/XSBind.c | 204 ++++++++++---------
runtime/perl/xs/XSBind.h | 57 +++---
6 files changed, 151 insertions(+), 131 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8875d01e/compiler/src/CFCPerl.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerl.c b/compiler/src/CFCPerl.c
index 2766da8..0b9f7b8 100644
--- a/compiler/src/CFCPerl.c
+++ b/compiler/src/CFCPerl.c
@@ -697,7 +697,8 @@ S_write_callbacks_c(CFCPerl *self) {
"S_finish_callback_obj(pTHX_ void *vself, const char *meth_name,\n"
" int nullable) {\n"
" SV *return_sv = SI_do_callback_sv(aTHX_ meth_name);\n"
- " cfish_Obj *retval = XSBind_perl_to_cfish(aTHX_ return_sv);\n"
+ " cfish_Obj *retval\n"
+ " = XSBind_perl_to_cfish_nullable(aTHX_ return_sv, CFISH_OBJ);\n"
" FREETMPS;\n"
" LEAVE;\n"
" if (!nullable && !retval) {\n"
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8875d01e/compiler/src/CFCPerlMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerlMethod.c b/compiler/src/CFCPerlMethod.c
index 01db539..9e3704f 100644
--- a/compiler/src/CFCPerlMethod.c
+++ b/compiler/src/CFCPerlMethod.c
@@ -218,7 +218,7 @@ S_self_assign_statement(CFCPerlMethod *self) {
CFCUtil_die("Not an object type: %s", type_c);
}
const char *class_var = CFCType_get_class_var(type);
- char pattern[] = "arg_%s = (%s)XSBind_sv_to_cfish_obj("
+ char pattern[] = "arg_%s = (%s)XSBind_perl_to_cfish_noinc("
"aTHX_ ST(0), %s, NULL);";
char *statement = CFCUtil_sprintf(pattern, self_name, type_c, class_var);
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8875d01e/compiler/src/CFCPerlTypeMap.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerlTypeMap.c b/compiler/src/CFCPerlTypeMap.c
index 795fdde..ef76755 100644
--- a/compiler/src/CFCPerlTypeMap.c
+++ b/compiler/src/CFCPerlTypeMap.c
@@ -52,7 +52,8 @@ CFCPerlTypeMap_from_perl(CFCType *type, const char *xs_var) {
else {
allocation = "NULL";
}
- const char pattern[] = "(%s*)XSBind_sv_to_cfish_obj(aTHX_ %s, %s, %s)";
+ const char pattern[]
+ = "(%s*)XSBind_perl_to_cfish_noinc(aTHX_ %s, %s, %s)";
result = CFCUtil_sprintf(pattern, struct_sym, xs_var, class_var,
allocation);
}
@@ -271,8 +272,8 @@ CFCPerlTypeMap_write_xs_typemap(CFCHierarchy *hierarchy) {
}
input = CFCUtil_cat(input, class_var, "_\n"
" $var = (", full_struct_sym,
- "*)XSBind_sv_to_cfish_obj(aTHX_ $arg, ", class_var,
- ", ", allocation, ");\n\n", NULL);
+ "*)XSBind_perl_to_cfish_noinc(aTHX_ $arg, ",
+ class_var, ", ", allocation, ");\n\n", NULL);
output = CFCUtil_cat(output, class_var, "_\n"
" $arg = (SV*)CFISH_Obj_To_Host((cfish_Obj*)$var);\n"
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8875d01e/runtime/perl/buildlib/Clownfish/Build/Binding.pm
----------------------------------------------------------------------
diff --git a/runtime/perl/buildlib/Clownfish/Build/Binding.pm b/runtime/perl/buildlib/Clownfish/Build/Binding.pm
index 2cbf62f..2b07aee 100644
--- a/runtime/perl/buildlib/Clownfish/Build/Binding.pm
+++ b/runtime/perl/buildlib/Clownfish/Build/Binding.pm
@@ -52,7 +52,7 @@ to_clownfish(sv)
SV *sv;
CODE:
{
- cfish_Obj *obj = XSBind_perl_to_cfish(aTHX_ sv);
+ cfish_Obj *obj = XSBind_perl_to_cfish_nullable(aTHX_ sv, CFISH_OBJ);
RETVAL = CFISH_OBJ_TO_SV_NOINC(obj);
}
OUTPUT: RETVAL
@@ -107,9 +107,10 @@ void
invoke_to_string(sv)
SV *sv;
PPCODE:
- cfish_Obj *obj = XSBind_sv_to_cfish_obj(aTHX_ sv, CFISH_OBJ, NULL);
+ cfish_Obj *obj = XSBind_perl_to_cfish(aTHX_ sv, CFISH_OBJ);
cfish_String *str = CFISH_Obj_To_String(obj);
CFISH_DECREF(str);
+ CFISH_DECREF(obj);
int
refcount(obj)
@@ -309,9 +310,7 @@ store(self, key, value_sv);
PPCODE:
{
cfish_Obj *value
- = (cfish_Obj*)XSBind_maybe_sv_to_cfish_obj(aTHX_ value_sv, CFISH_OBJ,
- CFISH_ALLOCA_OBJ(CFISH_STRING));
- if (value) { value = CFISH_INCREF(value); }
+ = (cfish_Obj*)XSBind_perl_to_cfish_nullable(aTHX_ value_sv, CFISH_OBJ);
CFISH_Hash_Store_IMP(self, key, value);
}
END_XS_CODE
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8875d01e/runtime/perl/xs/XSBind.c
----------------------------------------------------------------------
diff --git a/runtime/perl/xs/XSBind.c b/runtime/perl/xs/XSBind.c
index f426bc0..a4ec829 100644
--- a/runtime/perl/xs/XSBind.c
+++ b/runtime/perl/xs/XSBind.c
@@ -38,6 +38,10 @@
#define XSBIND_REFCOUNT_FLAG 1
#define XSBIND_REFCOUNT_SHIFT 1
+static bool
+S_maybe_perl_to_cfish(pTHX_ SV *sv, cfish_Class *klass, bool increment,
+ void *allocation, cfish_Obj **obj_ptr);
+
// Convert a Perl hash into a Clownfish Hash. Caller takes responsibility for
// a refcount.
static cfish_Hash*
@@ -74,119 +78,124 @@ XSBind_new_blank_obj(pTHX_ SV *either_sv) {
}
cfish_Obj*
-XSBind_sv_to_cfish_obj(pTHX_ SV *sv, cfish_Class *klass, void *allocation) {
- cfish_Obj *retval
- = XSBind_maybe_sv_to_cfish_obj(aTHX_ sv, klass, allocation);
- if (!retval) {
- THROW(CFISH_ERR, "Not a %o", CFISH_Class_Get_Name(klass));
+XSBind_perl_to_cfish(pTHX_ SV *sv, cfish_Class *klass) {
+ cfish_Obj *retval = NULL;
+ if (!S_maybe_perl_to_cfish(aTHX_ sv, klass, true, NULL, &retval)) {
+ THROW(CFISH_ERR, "Can't convert to %o", CFISH_Class_Get_Name(klass));
+ }
+ else if (!retval) {
+ THROW(CFISH_ERR, "%o must not be undef", CFISH_Class_Get_Name(klass));
}
return retval;
}
cfish_Obj*
-XSBind_maybe_sv_to_cfish_obj(pTHX_ SV *sv, cfish_Class *klass,
- void *allocation) {
+XSBind_perl_to_cfish_nullable(pTHX_ SV *sv, cfish_Class *klass) {
cfish_Obj *retval = NULL;
- if (XSBind_sv_defined(aTHX_ sv)) {
+ if (!S_maybe_perl_to_cfish(aTHX_ sv, klass, true, NULL, &retval)) {
+ THROW(CFISH_ERR, "Can't convert to %o", CFISH_Class_Get_Name(klass));
+ }
+ return retval;
+}
+
+cfish_Obj*
+XSBind_perl_to_cfish_noinc(pTHX_ SV *sv, cfish_Class *klass, void *allocation) {
+ cfish_Obj *retval = NULL;
+ if (!S_maybe_perl_to_cfish(aTHX_ sv, klass, false, allocation, &retval)) {
+ THROW(CFISH_ERR, "Can't convert to %o", CFISH_Class_Get_Name(klass));
+ }
+ else if (!retval) {
+ THROW(CFISH_ERR, "%o must not be undef", CFISH_Class_Get_Name(klass));
+ }
+ return retval;
+}
+
+static bool
+S_maybe_perl_to_cfish(pTHX_ SV *sv, cfish_Class *klass, bool increment,
+ void *allocation, cfish_Obj **obj_ptr) {
+ if (sv_isobject(sv)) {
+ cfish_String *class_name = CFISH_Class_Get_Name(klass);
// Assume that the class name is always NULL-terminated. Somewhat
// dangerous but should be safe.
- if (sv_isobject(sv)
- && sv_derived_from(sv, CFISH_Str_Get_Ptr8(CFISH_Class_Get_Name(klass)))
- ) {
+ if (sv_derived_from(sv, CFISH_Str_Get_Ptr8(class_name))) {
// Unwrap a real Clownfish object.
IV tmp = SvIV(SvRV(sv));
- retval = INT2PTR(cfish_Obj*, tmp);
- }
- else if (allocation &&
- (klass == CFISH_STRING
- || klass == CFISH_OBJ)
- ) {
- // Wrap the string from an ordinary Perl scalar inside a
- // stack String.
- STRLEN size;
- char *ptr = SvPVutf8(sv, size);
- retval = (cfish_Obj*)cfish_Str_new_stack_string(
- allocation, ptr, size);
+ cfish_Obj *obj = INT2PTR(cfish_Obj*, tmp);
+ if (increment) {
+ obj = CFISH_INCREF(obj);
+ }
+ *obj_ptr = obj;
+ return true;
}
- else if (SvROK(sv)) {
- // Attempt to convert Perl hashes and arrays into their Clownfish
- // analogues.
- SV *inner = SvRV(sv);
- if (SvTYPE(inner) == SVt_PVAV && klass == CFISH_VECTOR) {
- retval = (cfish_Obj*)
+ }
+ else if (SvROK(sv)) {
+ cfish_Obj *obj = NULL;
+ SV *inner = SvRV(sv);
+ svtype inner_type = SvTYPE(inner);
+
+ // Attempt to convert Perl hashes and arrays into their Clownfish
+ // analogues.
+ if (inner_type == SVt_PVAV) {
+ if (klass == CFISH_VECTOR || klass == CFISH_OBJ) {
+ obj = (cfish_Obj*)
S_perl_array_to_cfish_array(aTHX_ (AV*)inner);
}
- else if (SvTYPE(inner) == SVt_PVHV && klass == CFISH_HASH) {
- retval = (cfish_Obj*)
+ }
+ else if (inner_type == SVt_PVHV) {
+ if (klass == CFISH_HASH || klass == CFISH_OBJ) {
+ obj = (cfish_Obj*)
S_perl_hash_to_cfish_hash(aTHX_ (HV*)inner);
}
+ }
+ else if (inner_type < SVt_PVAV && !SvOK(inner)) {
+ // Reference to undef. After cloning a Perl interpeter,
+ // most Clownfish objects look like this after they're
+ // CLONE_SKIPped.
+ *obj_ptr = NULL;
+ return true;
+ }
- if (retval) {
+ if (obj) {
+ if (!increment) {
// Mortalize the converted object -- which is somewhat
// dangerous, but is the only way to avoid requiring that the
// caller take responsibility for a refcount.
- SV *mortal = XSBind_cfish_obj_to_sv(aTHX_ retval);
- CFISH_DECREF(retval);
+ SV *mortal = XSBind_cfish_obj_to_sv(aTHX_ obj);
+ CFISH_DECREF(obj);
sv_2mortal(mortal);
}
+
+ *obj_ptr = obj;
+ return true;
}
}
+ else if (!XSBind_sv_defined(aTHX_ sv)) {
+ *obj_ptr = NULL;
+ return true;
+ }
- return retval;
-}
-
-cfish_Obj*
-XSBind_perl_to_cfish(pTHX_ SV *sv) {
- cfish_Obj *retval = NULL;
-
- if (XSBind_sv_defined(aTHX_ sv)) {
- bool is_undef = false;
+ // Stringify as last resort.
+ if (klass == CFISH_STRING || klass == CFISH_OBJ) {
+ STRLEN size;
+ char *ptr = SvPVutf8(sv, size);
- if (SvROK(sv)) {
- // Deep conversion of references.
- SV *inner = SvRV(sv);
- if (SvTYPE(inner) == SVt_PVAV) {
- retval = (cfish_Obj*)
- S_perl_array_to_cfish_array(aTHX_ (AV*)inner);
- }
- else if (SvTYPE(inner) == SVt_PVHV) {
- retval = (cfish_Obj*)
- S_perl_hash_to_cfish_hash(aTHX_ (HV*)inner);
- }
- else if (sv_isobject(sv)
- && sv_derived_from(sv, "Clownfish::Obj")
- ) {
- IV tmp = SvIV(inner);
- retval = INT2PTR(cfish_Obj*, tmp);
- (void)CFISH_INCREF(retval);
- }
- else if (!XSBind_sv_defined(aTHX_ inner)) {
- // Reference to undef. After cloning a Perl interpeter,
- // most Clownfish objects look like this after they're
- // CLONE_SKIPped.
- is_undef = true;
- }
- }
-
- // It's either a plain scalar or a non-Clownfish Perl object, so
- // stringify.
- if (!retval && !is_undef) {
- STRLEN len;
- char *ptr = SvPVutf8(sv, len);
- retval = (cfish_Obj*)cfish_Str_new_from_trusted_utf8(ptr, len);
+ if (increment) {
+ *obj_ptr = (cfish_Obj*)cfish_Str_new_from_trusted_utf8(ptr, size);
+ return true;
}
- }
- else if (sv) {
- // Deep conversion of raw AVs and HVs.
- if (SvTYPE(sv) == SVt_PVAV) {
- retval = (cfish_Obj*)S_perl_array_to_cfish_array(aTHX_ (AV*)sv);
- }
- else if (SvTYPE(sv) == SVt_PVHV) {
- retval = (cfish_Obj*)S_perl_hash_to_cfish_hash(aTHX_ (HV*)sv);
+ else {
+ // Wrap the string from an ordinary Perl scalar inside a
+ // stack String.
+ if (!allocation) {
+ CFISH_THROW(CFISH_ERR, "Allocation for stack string missing");
+ }
+ *obj_ptr = (cfish_Obj*)cfish_Str_new_stack_string(
+ allocation, ptr, size);
+ return true;
}
}
- return retval;
+ return false;
}
const char*
@@ -231,7 +240,8 @@ S_perl_hash_to_cfish_hash(pTHX_ HV *phash) {
SV *value_sv = HeVAL(entry);
// Recurse.
- cfish_Obj *value = XSBind_perl_to_cfish(aTHX_ value_sv);
+ cfish_Obj *value
+ = XSBind_perl_to_cfish_nullable(aTHX_ value_sv, CFISH_OBJ);
CFISH_Hash_Store_Utf8(retval, key_str, key_len, value);
}
@@ -248,7 +258,8 @@ S_perl_array_to_cfish_array(pTHX_ AV *parray) {
for (uint32_t i = 0; i < size; i++) {
SV **elem_sv = av_fetch(parray, i, false);
if (elem_sv) {
- cfish_Obj *elem = XSBind_perl_to_cfish(aTHX_ *elem_sv);
+ cfish_Obj *elem
+ = XSBind_perl_to_cfish_nullable(aTHX_ *elem_sv, CFISH_OBJ);
if (elem) { CFISH_Vec_Store(retval, i, elem); }
}
}
@@ -350,10 +361,11 @@ S_extract_from_sv(pTHX_ SV *value, void *target, const char *label,
valid_assignment = true;
break;
case XSBIND_WANT_OBJ: {
- cfish_Obj *object
- = XSBind_maybe_sv_to_cfish_obj(aTHX_ value, klass,
- allocation);
- if (object) {
+ cfish_Obj *object = NULL;
+ bool success
+ = S_maybe_perl_to_cfish(aTHX_ value, klass, false,
+ allocation, &object);
+ if (success && object) {
*((cfish_Obj**)target) = object;
valid_assignment = true;
}
@@ -729,7 +741,8 @@ cfish_Class_fresh_host_methods(cfish_String *class_name) {
PUTBACK;
call_pv("Clownfish::Class::_fresh_host_methods", G_SCALAR);
SPAGAIN;
- cfish_Vector *methods = (cfish_Vector*)XSBind_perl_to_cfish(aTHX_ POPs);
+ cfish_Vector *methods
+ = (cfish_Vector*)XSBind_perl_to_cfish(aTHX_ POPs, CFISH_VECTOR);
PUTBACK;
FREETMPS;
LEAVE;
@@ -748,10 +761,9 @@ cfish_Class_find_parent_class(cfish_String *class_name) {
PUTBACK;
call_pv("Clownfish::Class::_find_parent_class", G_SCALAR);
SPAGAIN;
- SV *parent_class_sv = POPs;
+ cfish_String *parent_class = (cfish_String*)
+ XSBind_perl_to_cfish_nullable(aTHX_ POPs, CFISH_STRING);
PUTBACK;
- cfish_String *parent_class
- = (cfish_String*)XSBind_perl_to_cfish(aTHX_ parent_class_sv);
FREETMPS;
LEAVE;
return parent_class;
@@ -824,8 +836,8 @@ cfish_Err_get_error() {
PUTBACK;
call_pv("Clownfish::Err::get_error", G_SCALAR);
SPAGAIN;
- cfish_Err *error = (cfish_Err*)XSBind_perl_to_cfish(aTHX_ POPs);
- if (error) { CFISH_CERTIFY(error, CFISH_ERR); }
+ cfish_Err *error
+ = (cfish_Err*)XSBind_perl_to_cfish_nullable(aTHX_ POPs, CFISH_ERR);
PUTBACK;
FREETMPS;
LEAVE;
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8875d01e/runtime/perl/xs/XSBind.h
----------------------------------------------------------------------
diff --git a/runtime/perl/xs/XSBind.h b/runtime/perl/xs/XSBind.h
index 5fabb32..609c5bb 100644
--- a/runtime/perl/xs/XSBind.h
+++ b/runtime/perl/xs/XSBind.h
@@ -60,25 +60,6 @@ cfish_XSBind_sv_defined(pTHX_ SV *sv) {
return !!SvOK(sv);
}
-/** If the SV contains a Clownfish object which passes an "isa" test against the
- * passed-in Class, return a pointer to it. If not, but
- * `allocation` is non-NULL and a String would satisfy the
- * "isa" test, stringify the SV, create a stack String using
- * `allocation`, assign the SV's string to it, and return that
- * instead. If all else fails, throw an exception.
- */
-CFISH_VISIBLE cfish_Obj*
-cfish_XSBind_sv_to_cfish_obj(pTHX_ SV *sv, cfish_Class *klass,
- void *allocation);
-
-/** As XSBind_sv_to_cfish_obj above, but returns NULL instead of throwing an
- * exception.
- */
-CFISH_VISIBLE cfish_Obj*
-cfish_XSBind_maybe_sv_to_cfish_obj(pTHX_ SV *sv, cfish_Class *klass,
- void *allocation);
-
-
/** Derive an SV from a Clownfish object. If the Clownfish object is NULL, the SV
* will be undef. Doesn't invoke To_Host and always returns a reference to a
* Clownfish::Obj.
@@ -123,12 +104,38 @@ cfish_XSBind_cfish_to_perl(pTHX_ cfish_Obj *obj) {
return obj ? (SV*)CFISH_Obj_To_Host(obj) : newSV(0);
}
-/** Deep conversion of Perl data structures to Clownfish objects -- Perl hash
- * to Hash, Perl array to Vector, Clownfish objects stripped of their
- * wrappers, and everything else stringified and turned to a String.
+/** Convert a Perl SV to a Clownfish object of class `klass`.
+ *
+ * - If the SV contains a Clownfish object which passes an "isa" test against
+ * `klass`, return a pointer to it.
+ * - If the SV contains an arrayref and `klass` is VECTOR or OBJ, perform a
+ * deep conversion of the Perl array to a Vector.
+ * - If the SV contains a hashref and `klass` is HASH or OBJ, perform a
+ * deep conversion of the Perl hash to a Hash.
+ * - If `klass` is STRING or OBJ, stringify and return a String.
+ * - If all else fails, throw an exception.
+ *
+ * Returns an non-NULL, "incremented" object that must be decref'd at some
+ * point.
+ */
+CFISH_VISIBLE cfish_Obj*
+cfish_XSBind_perl_to_cfish(pTHX_ SV *sv, cfish_Class *klass);
+
+/** As XSBind_perl_to_cfish above, but returns NULL if the SV is undefined
+ * or a reference to an undef.
+ */
+CFISH_VISIBLE cfish_Obj*
+cfish_XSBind_perl_to_cfish_nullable(pTHX_ SV *sv, cfish_Class *klass);
+
+/** As XSBind_perl_to_cfish above, but returns an object that can be used for
+ * a while with no need to decref.
+ *
+ * If `klass` is STRING or OBJ, `allocation` must point to stack-allocated
+ * memory that can hold a String. Otherwise, `allocation` should be NULL.
*/
CFISH_VISIBLE cfish_Obj*
-cfish_XSBind_perl_to_cfish(pTHX_ SV *sv);
+cfish_XSBind_perl_to_cfish_noinc(pTHX_ SV *sv, cfish_Class *klass,
+ void *allocation);
/** Return the contents of the hash entry's key as UTF-8.
*/
@@ -301,12 +308,12 @@ cfish_XSBind_allot_params(pTHX_ SV** stack, int32_t start,
*/
#define XSBind_new_blank_obj cfish_XSBind_new_blank_obj
#define XSBind_sv_defined cfish_XSBind_sv_defined
-#define XSBind_sv_to_cfish_obj cfish_XSBind_sv_to_cfish_obj
-#define XSBind_maybe_sv_to_cfish_obj cfish_XSBind_maybe_sv_to_cfish_obj
#define XSBind_cfish_obj_to_sv cfish_XSBind_cfish_obj_to_sv
#define XSBind_cfish_obj_to_sv_noinc cfish_XSBind_cfish_obj_to_sv_noinc
#define XSBind_cfish_to_perl cfish_XSBind_cfish_to_perl
#define XSBind_perl_to_cfish cfish_XSBind_perl_to_cfish
+#define XSBind_perl_to_cfish_nullable cfish_XSBind_perl_to_cfish_nullable
+#define XSBind_perl_to_cfish_noinc cfish_XSBind_perl_to_cfish_noinc
#define XSBind_hash_key_to_utf8 cfish_XSBind_hash_key_to_utf8
#define XSBind_trap cfish_XSBind_trap
#define XSBind_allot_params cfish_XSBind_allot_params