/* * Convert the array to a scalar if allowed, and apply the builtin function * to it. The where argument is passed onto Py_EnterRecursiveCall when the * array contains python objects. */ NPY_NO_EXPORT PyObject * array_scalar_forward(PyArrayObject *v, PyObject *(*builtin_func)(PyObject *), const char *where) { PyObject *scalar; if (PyArray_SIZE(v) != 1) { PyErr_SetString(PyExc_TypeError, "only size-1 arrays can be"\ " converted to Python scalars"); return NULL; } scalar = PyArray_GETITEM(v, PyArray_DATA(v)); if (scalar == NULL) { return NULL; } /* Need to guard against recursion if our array holds references */ if (PyDataType_REFCHK(PyArray_DESCR(v))) { PyObject *res; if (Npy_EnterRecursiveCall(where) != 0) { Py_DECREF(scalar); return NULL; } res = builtin_func(scalar); Py_DECREF(scalar); Py_LeaveRecursiveCall(); return res; } else { PyObject *res; res = builtin_func(scalar); Py_DECREF(scalar); return res; } }
TypedValue* zend_wrap_func( ActRec* ar, zend_ext_func builtin_func, int numParams, bool isReturnRef) { TSRMLS_FETCH(); // Prepare the arguments and return value before they are // exposed to the PHP extension zPrepArgs(ar); // Using Variant so exceptions will decref them Variant return_value_var(Variant::NullInit{}); auto const return_value = return_value_var.asTypedValue(); tvBox(return_value); Variant this_ptr_var(Variant::NullInit{}); auto const this_ptr = this_ptr_var.asTypedValue(); tvBox(this_ptr); if (ar->hasThis()) { tvWriteObject( ar->getThis(), this_ptr->m_data.pref->tv() ); } auto *return_value_ptr = &return_value->m_data.pref; // Clear any stored exception ZendExceptionStore& exceptionStore = ZendExceptionStore::getInstance(); exceptionStore.clear(); // Invoke the PHP extension function/method ZendExecutionStack::pushHHVMStack(); try { builtin_func( ar->numArgs(), return_value->m_data.pref, return_value_ptr, this_ptr_var.isNull() ? nullptr : this_ptr->m_data.pref, 1 TSRMLS_CC ); } catch (...) { ZendExecutionStack::popHHVMStack(); throw; } ZendExecutionStack::popHHVMStack(); // If an exception was caught, rethrow it if (!exceptionStore.empty()) { exceptionStore.rethrow(); } // Take care of freeing the args, tearing down the ActRec, // and moving the return value to the right place frame_free_locals_inl(ar, numParams); memcpy(&ar->m_r, return_value, sizeof(TypedValue)); return_value->m_type = KindOfNull; if (isReturnRef) { if (!ar->m_r.m_data.pref->isReferenced()) { tvUnbox(&ar->m_r); } } else { tvUnbox(&ar->m_r); } return &ar->m_r; }