#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "Python.h" #include "py2pl.h" #include "util.h" #ifdef EXPOSE_PERL #include "perlmodule.h" #endif SV* py_true; SV* py_false; /**************************** * SV* Py2Pl(PyObject *obj) * * Converts arbitrary Python data structures to Perl data structures * Note on references: does not Py_DECREF(obj). * * Modifications by Eric Wilhelm 2004-07-11 marked as elw * ****************************/ SV *Py2Pl(PyObject * const obj) { /* elw: see what python says things are */ int const is_string = PY_IS_STRING(obj); #ifdef I_PY_DEBUG PyObject *this_type = PyObject_Type(obj); /* new reference */ PyObject *t_string = PyObject_Str(this_type); /* new reference */ #if PY_MAJOR_VERSION >= 3 PyObject *type_str_bytes = PyUnicode_AsUTF8String(t_string); /* new reference */ char *type_str = PyBytes_AsString(type_str_bytes); #else char *type_str = PyString_AsString(t_string); #endif Printf(("type is %s\n", type_str)); printf("Py2Pl object:\n\t"); PyObject_Print(obj, stdout, Py_PRINT_RAW); printf("\ntype:\n\t"); PyObject_Print(this_type, stdout, Py_PRINT_RAW); printf("\n"); Printf(("String check: %i\n", is_string)); Printf(("Number check: %i\n", PyNumber_Check(obj))); Printf(("Int check: %i\n", PyInt_Check(obj))); Printf(("Long check: %i\n", PyLong_Check(obj))); Printf(("Float check: %i\n", PyFloat_Check(obj))); Printf(("Type check: %i\n", PyType_Check(obj))); #if PY_MAJOR_VERSION < 3 Printf(("Class check: %i\n", PyClass_Check(obj))); Printf(("Instance check: %i\n", PyInstance_Check(obj))); #endif Printf(("Dict check: %i\n", PyDict_Check(obj))); Printf(("Mapping check: %i\n", PyMapping_Check(obj))); Printf(("Sequence check: %i\n", PySequence_Check(obj))); Printf(("Iter check: %i\n", PyIter_Check(obj))); Printf(("Function check: %i\n", PyFunction_Check(obj))); Printf(("Module check: %i\n", PyModule_Check(obj))); Printf(("Method check: %i\n", PyMethod_Check(obj))); #if PY_MAJOR_VERSION < 3 if ((obj->ob_type->tp_flags & Py_TPFLAGS_HEAPTYPE)) printf("heaptype true\n"); if ((obj->ob_type->tp_flags & Py_TPFLAGS_HAVE_CLASS)) printf("has class\n"); #else Py_DECREF(type_str_bytes); #endif Py_DECREF(t_string); Py_DECREF(this_type); #endif /* elw: this needs to be early */ /* None (like undef) */ if (!obj || obj == Py_None) { Printf(("Py2Pl: Py_None\n")); return &PL_sv_undef; } else #ifdef EXPOSE_PERL /* unwrap Perl objects */ if (PerlObjObject_Check(obj)) { Printf(("Py2Pl: Obj_object\n")); return ((PerlObj_object *) obj)->obj; } /* unwrap Perl code refs */ else if (PerlSubObject_Check(obj)) { Printf(("Py2Pl: Sub_object\n")); SV * ref = ((PerlSub_object *) obj)->ref; if (! ref) { /* probably an inherited method */ if (! ((PerlSub_object *) obj)->obj) croak("Error: could not find a code reference or object method for PerlSub"); SV * const sub_obj = (SV*)SvRV(((PerlSub_object *) obj)->obj); HV * const pkg = SvSTASH(sub_obj); #if PY_MAJOR_VERSION >= 3 char * const sub = PyBytes_AsString(((PerlSub_object *) obj)->sub); #else PyObject *obj_sub_str = PyObject_Str(((PerlSub_object *) obj)->sub); /* new ref. */ char * const sub = PyString_AsString(obj_sub_str); #endif GV * const gv = Perl_gv_fetchmethod_autoload(aTHX_ pkg, sub, TRUE); if (gv && isGV(gv)) { ref = (SV *)GvCV(gv); } #if PY_MAJOR_VERSION < 3 Py_DECREF(obj_sub_str); #endif } return newRV_inc((SV *) ref); } else #endif /* wrap an instance of a Python class */ /* elw: here we need to make these look like instances: */ if (PY_IS_OBJECT(obj)) { /* This is a Python class instance -- bless it into an * Inline::Python::Object. If we're being called from an * Inline::Python class, it will be re-blessed into whatever * class that is. */ SV * const inst_ptr = newSViv(0); SV * const inst = newSVrv(inst_ptr, "Inline::Python::Object");; _inline_magic priv; /* set up magic */ priv.key = INLINE_MAGIC_KEY; sv_magic(inst, inst, PERL_MAGIC_ext, (char *) &priv, sizeof(priv)); MAGIC * const mg = mg_find(inst, PERL_MAGIC_ext); mg->mg_virtual = &inline_mg_vtbl; sv_setiv(inst, (IV) obj); /*SvREADONLY_on(inst); */ /* to uncomment this means I can't re-bless it */ Py_INCREF(obj); Printf(("Py2Pl: Instance. Obj: %p, inst_ptr: %p\n", obj, inst_ptr)); sv_2mortal(inst_ptr); return inst_ptr; } /* a tuple or a list */ else if (PySequence_Check(obj) && !is_string) { AV * const retval = newAV(); int i; int const sz = PySequence_Length(obj); Printf(("sequence (%i)\n", sz)); for (i = 0; i < sz; i++) { PyObject * const tmp = PySequence_GetItem(obj, i); /* new reference */ SV * const next = Py2Pl(tmp); av_push(retval, next); if (sv_isobject(next)) // needed because objects get mortalized in Py2Pl SvREFCNT_inc(next); Py_DECREF(tmp); } if (PyTuple_Check(obj)) { _inline_magic priv; priv.key = TUPLE_MAGIC_KEY; sv_magic((SV * const)retval, (SV * const)NULL, PERL_MAGIC_ext, (char *) &priv, sizeof(priv)); } return newRV_noinc((SV *) retval); } /* a real plain dictionary */ else if (obj->ob_type == &PyDict_Type) { HV * const retval = newHV(); int i; int const sz = PyMapping_Length(obj); PyObject * const keys = PyMapping_Keys(obj); /* new reference */ PyObject * const vals = PyMapping_Values(obj); /* new reference */ Printf(("Py2Pl: dict/map\n")); Printf(("mapping (%i)\n", sz)); for (i = 0; i < sz; i++) { PyObject * const key = PySequence_GetItem(keys, i), /* new reference */ * const val = PySequence_GetItem(vals, i); /* new reference */ SV * const sv_val = Py2Pl(val); char * key_val; if (PyUnicode_Check(key)) { PyObject * const utf8_string = PyUnicode_AsUTF8String(key); /* new reference */ #if PY_MAJOR_VERSION >= 3 key_val = PyBytes_AsString(utf8_string); SV * const utf8_key = newSVpv(key_val, PyBytes_Size(utf8_string)); #else key_val = PyString_AsString(utf8_string); SV * const utf8_key = newSVpv(key_val, PyString_Size(utf8_string)); #endif SvUTF8_on(utf8_key); hv_store_ent(retval, utf8_key, sv_val, 0); sv_2mortal(utf8_key); Py_DECREF(utf8_string); } else { PyObject * s = NULL; #if PY_MAJOR_VERSION >= 3 PyObject * s_bytes = NULL; if (PyBytes_Check(key)) { key_val = PyBytes_AsString(key); #else if (PyString_Check(key)) { key_val = PyString_AsString(key); #endif } else { /* Warning -- encountered a non-string key value while converting a * Python dictionary into a Perl hash. Perl can only use strings as * key values. Using Python's string representation of the key as * Perl's key value. */ s = PyObject_Str(key); /* new reference */ #if PY_MAJOR_VERSION >= 3 s_bytes = PyUnicode_AsUTF8String(s); /* new reference */ key_val = PyBytes_AsString(s_bytes); #else key_val = PyString_AsString(s); #endif if (PL_dowarn) warn("Stringifying non-string hash key value: '%s'", key_val); } if (!key_val) { croak("Invalid key on key %i of mapping\n", i); } hv_store(retval, key_val, strlen(key_val), sv_val, 0); #if PY_MAJOR_VERSION >= 3 Py_XDECREF(s_bytes); #endif Py_XDECREF(s); } if (sv_isobject(sv_val)) // needed because objects get mortalized in Py2Pl SvREFCNT_inc(sv_val); Py_DECREF(key); Py_DECREF(val); } Py_DECREF(keys); Py_DECREF(vals); return newRV_noinc((SV *) retval); } /* a boolean */ else if (PyBool_Check(obj)) { Printf(("Py2Pl: boolean\n")); if (obj == Py_True) return py_true; if (obj == Py_False) return py_false; croak( "Internal error: Pl2Py() caught a bool that is not True or False!? at %s, line %i.\n", __FILE__, __LINE__ ); } /* an int */ else if (PyInt_Check(obj)) { SV * const sv = newSViv(PyInt_AsLong(obj)); Printf(("Py2Pl: integer\n")); return sv; } /* a float */ else if (PyFloat_Check(obj)) { SV * const sv = newSVnv(PyFloat_AsDouble(obj)); Printf(("Py2Pl: float\n")); return sv; } /* a function or method */ else if (PyFunction_Check(obj) || PyMethod_Check(obj)) { SV * const inst_ptr = newSViv(0); SV * const inst = newSVrv(inst_ptr, "Inline::Python::Function"); _inline_magic priv; /* set up magic */ priv.key = INLINE_MAGIC_KEY; sv_magic(inst, inst, '~', (char *) &priv, sizeof(priv)); MAGIC * const mg = mg_find(inst, '~'); mg->mg_virtual = &inline_mg_vtbl; sv_setiv(inst, (IV) obj); /*SvREADONLY_on(inst); */ /* to uncomment this means I can't re-bless it */ Py_INCREF(obj); Printf(("Py2Pl: Instance. Obj: %p, inst_ptr: %p\n", obj, inst_ptr)); sv_2mortal(inst_ptr); return inst_ptr; } #if PY_MAJOR_VERSION >= 3 /* In P3, I stringify Bytes explicitly to avoid "b'fdsfd'" as Perl string. * "PyObject_Str" is fine for string object. */ else if (PyBytes_Check(obj)) { char * const str = PyBytes_AsString(obj); SV * const s2 = newSVpv(str, PyBytes_Size(obj)); Printf(("Py2Pl: bytes \n")); return s2; } #endif else if (PyUnicode_Check(obj)) { PyObject * const string = PyUnicode_AsUTF8String(obj); /* new reference */ if (!string) { Printf(("Py2Pl: string is NULL!? -> Py_None\n")); return &PL_sv_undef; } #if PY_MAJOR_VERSION >= 3 char * const str = PyBytes_AsString(string); SV * const s2 = newSVpv(str, PyBytes_Size(string)); #else char * const str = PyString_AsString(string); SV * const s2 = newSVpv(str, PyString_Size(string)); #endif SvUTF8_on(s2); Printf(("Py2Pl: utf8 string \n")); Py_DECREF(string); return s2; } /* P2: a string (or number). P3: number*/ else { PyObject * const string = PyObject_Str(obj); /* new reference */ if (!string) { Printf(("Py2Pl: string is NULL!? -> Py_None\n")); return &PL_sv_undef; } #if PY_MAJOR_VERSION >= 3 PyObject * const string_as_bytes = PyUnicode_AsUTF8String(string); /* new reference */ char * const str = PyBytes_AsString(string_as_bytes); SV * const s2 = newSVpv(str, PyBytes_Size(string_as_bytes)); Py_DECREF(string_as_bytes); #else char * const str = PyString_AsString(string); SV * const s2 = newSVpv(str, PyString_Size(string)); #endif Printf(("Py2Pl: string / number\n")); Py_DECREF(string); return s2; } } /**************************** * SV* Pl2Py(PyObject *obj) * * Converts arbitrary Perl data structures to Python data structures ****************************/ PyObject *Pl2Py(SV * const obj) { PyObject *o; /* an object */ if (sv_isobject(obj)) { /* We know it's a blessed reference: */ SV * const obj_deref = SvRV(obj); /* First check if it's one of the Inline::Python::Boolean values */ if (obj == py_true || obj_deref == SvRV(py_true)) Py_RETURN_TRUE; if (obj == py_false || obj_deref == SvRV(py_false)) Py_RETURN_FALSE; /* * Now it's time to check whether it's *really* a blessed Perl object, * or whether it's a blessed Python object with '~' magic set. * If '~' magic is set, we 'unwrap' it into its Python object. * If not, we wrap it up in a PerlObj_object. */ /* check for magic! */ MAGIC * const mg = mg_find(obj_deref, '~'); if (mg && Inline_Magic_Check(mg->mg_ptr)) { IV const ptr = SvIV(obj_deref); if (!ptr) { croak ("Internal error: Pl2Py() caught NULL PyObject* at %s, line %i.\n", __FILE__, __LINE__); } o = (PyObject *) ptr; Py_INCREF(o); } else { HV * const stash = SvSTASH(obj_deref); char * const pkg = HvNAME(stash); SV * const full_pkg = newSVpvf("main::%s::", pkg); Printf(("A Perl object (%s, refcnt: %i). Wrapping...\n", SvPV(full_pkg, PL_na), SvREFCNT(obj))); #if PY_MAJOR_VERSION >= 3 PyObject * const pkg_py = PyBytes_FromString(SvPV(full_pkg, PL_na)); #else PyObject * const pkg_py = PyString_FromString(SvPV(full_pkg, PL_na)); #endif o = newPerlObj_object(obj, pkg_py); Py_DECREF(pkg_py); SvREFCNT_dec(full_pkg); } } /* An integer */ else if (SvIOK(obj)) { Printf(("integer\n")); o = PyInt_FromLong((long) SvIV(obj)); } /* A floating-point number */ else if (SvNOK(obj)) { o = PyFloat_FromDouble(SvNV(obj)); } /* A string */ else if (SvPOKp(obj)) { STRLEN len; char * const str = SvPV(obj, len); Printf(("string = ")); Printf(("%s\n", str)); #if PY_MAJOR_VERSION >= 3 if (SvUTF8(obj) || is_ascii_string((U8*) str, len)) o = PyUnicode_DecodeUTF8(str, len, "replace"); else o = PyBytes_FromStringAndSize(str, len); #else if (SvUTF8(obj)) o = PyUnicode_DecodeUTF8(str, len, "replace"); else o = PyString_FromStringAndSize(str, len); #endif Printf(("string ok\n")); } /* An array */ else if (SvROK(obj) && SvTYPE(SvRV(obj)) == SVt_PVAV) { AV * const av = (AV *) SvRV(obj); int const len = av_len(av) + 1; int i; if (py_is_tuple(obj)) { o = PyTuple_New(len); Printf(("tuple (%i)\n", len)); for (i = 0; i < len; i++) { SV ** const tmp = av_fetch(av, i, 0); if (tmp) { PyObject * const tmp_py = Pl2Py(*tmp); PyTuple_SetItem(o, i, tmp_py); } else { Printf(("Got a NULL from av_fetch for element %i. Might be a bug!", i)); Py_INCREF(Py_None); PyTuple_SetItem(o, i, Py_None); } } } else { o = PyList_New(len); Printf(("array (%i)\n", len)); for (i = 0; i < len; i++) { SV ** const tmp = av_fetch(av, i, 0); if (tmp) { PyObject * const tmp_py = Pl2Py(*tmp); PyList_SetItem(o, i, tmp_py); } else { Printf(("Got a NULL from av_fetch for element %i. Might be a bug!", i)); Py_INCREF(Py_None); PyList_SetItem(o, i, Py_None); } } } } /* A hash */ else if (SvROK(obj) && SvTYPE(SvRV(obj)) == SVt_PVHV) { HV * const hv = (HV *) SvRV(obj); int const len = hv_iterinit(hv); int i; o = PyDict_New(); Printf(("hash (%i)\n", len)); for (i = 0; i < len; i++) { HE * const next = hv_iternext(hv); SV * const key = hv_iterkeysv(next); if (!key) croak("Hash entry without key!?"); STRLEN len; char * const key_str = SvPV(key, len); PyObject *py_key; #if PY_MAJOR_VERSION >= 3 if (SvUTF8(key) || is_ascii_string((U8*) key_str, len)) py_key = PyUnicode_DecodeUTF8(key_str, len, "replace"); else py_key = PyBytes_FromStringAndSize(key_str, len); #else if (SvUTF8(key)) py_key = PyUnicode_DecodeUTF8(key_str, len, "replace"); else py_key = PyString_FromStringAndSize(key_str, len); #endif PyObject * const val = Pl2Py(hv_iterval(hv, next)); PyDict_SetItem(o, py_key, val); Py_DECREF(py_key); Py_DECREF(val); } Printf(("returning from hash conversion.\n")); } /* A code ref */ else if (SvROK(obj) && SvTYPE(SvRV(obj)) == SVt_PVCV) { /* wrap this into a PerlSub_object */ o = (PyObject *) newPerlSub_object(NULL, NULL, obj); } else { Printf(("undef -> None\n")); o = Py_None; Py_INCREF(Py_None); } Printf(("returning from Pl2Py\n")); return o; } void croak_python_exception() { PyObject *ex_type, *ex_value, *ex_traceback; if (PyErr_ExceptionMatches(PyExc_Perl)) { PyErr_Fetch(&ex_type, &ex_value, &ex_traceback); PyErr_NormalizeException(&ex_type, &ex_value, &ex_traceback); PyObject *perl_exception_args = PyObject_GetAttrString(ex_value, "args"); PyObject *perl_exception = PySequence_GetItem(perl_exception_args, 0); SV *perl_exception_object = Py2Pl(perl_exception); sv_2mortal(perl_exception_object); SV *errsv = get_sv("@", GV_ADD); sv_setsv(errsv, perl_exception_object); croak(NULL); Py_DECREF(perl_exception); Py_DECREF(perl_exception_args); } else { PyErr_Fetch(&ex_type, &ex_value, &ex_traceback); PyErr_NormalizeException(&ex_type, &ex_value, &ex_traceback); PyObject * const ex_message = PyObject_Str(ex_value); /* new reference */ #if PY_MAJOR_VERSION >= 3 PyObject * const ex_message_bytes = PyUnicode_AsUTF8String(ex_message); /* new reference */ char * const c_ex_message = PyBytes_AsString(ex_message_bytes); #else char * const c_ex_message = PyString_AsString(ex_message); #endif if (ex_traceback) { PyObject * const tb_lineno = PyObject_GetAttrString(ex_traceback, "tb_lineno"); croak("%s: %s at line %i\n", ((PyTypeObject *)ex_type)->tp_name, c_ex_message, PyInt_AsLong(tb_lineno)); Py_DECREF(tb_lineno); } else { croak("%s: %s", ((PyTypeObject *)ex_type)->tp_name, c_ex_message); } #if PY_MAJOR_VERSION >= 3 Py_DECREF(ex_message_bytes); #endif Py_DECREF(ex_message); } Py_DECREF(ex_type); Py_DECREF(ex_value); Py_XDECREF(ex_traceback); } /* * vim: expandtab shiftwidth=4 softtabstop=4 cinoptions='\:2=2' : */