static int ue_PyUScriptStruct_setattro(ue_PyUScriptStruct *self, PyObject *attr_name, PyObject *value) { // first of all check for UProperty if (PyUnicodeOrString_Check(attr_name)) { char *attr = PyUnicode_AsUTF8(attr_name); // first check for property UProperty *u_property = get_field_from_name(self->u_struct, attr); if (u_property) { if (ue_py_convert_pyobject(value, u_property, self->data, 0)) { return 0; } PyErr_SetString(PyExc_ValueError, "invalid value for UProperty"); return -1; } } return PyObject_GenericSetAttr((PyObject *)self, attr_name, value); }
static PyObject *py_ue_uscriptstruct_set_field(ue_PyUScriptStruct *self, PyObject * args) { char *name; PyObject *value; int index = 0; if (!PyArg_ParseTuple(args, "sO|i:set_field", &name, &value, &index)) { return nullptr; } UProperty *u_property = self->u_struct->FindPropertyByName(FName(UTF8_TO_TCHAR(name))); if (!u_property) return PyErr_Format(PyExc_Exception, "unable to find property %s", name); if (!ue_py_convert_pyobject(value, u_property, self->data, index)) { return PyErr_Format(PyExc_Exception, "unable to set property %s", name); } Py_RETURN_NONE; }
void UPythonFunction::CallPythonCallable(FFrame& Stack, RESULT_DECL) { FScopePythonGIL gil; UPythonFunction *function = static_cast<UPythonFunction *>(Stack.CurrentNativeFunction); bool on_error = false; bool is_static = function->HasAnyFunctionFlags(FUNC_Static); // count the number of arguments Py_ssize_t argn = (Stack.Object && !is_static) ? 1 : 0; TFieldIterator<UProperty> IArgs(function); for (; IArgs && ((IArgs->PropertyFlags & (CPF_Parm | CPF_ReturnParm)) == CPF_Parm); ++IArgs) { argn++; } #if defined(UEPY_MEMORY_DEBUG) UE_LOG(LogPython, Warning, TEXT("Initializing %d parameters"), argn); #endif PyObject *py_args = PyTuple_New(argn); if (Stack.Object && !is_static) { PyObject *py_obj = (PyObject *)ue_get_python_wrapper(Stack.Object); if (!py_obj) { unreal_engine_py_log_error(); on_error = true; } else { Py_INCREF(py_obj); PyTuple_SetItem(py_args, 0, py_obj); } } uint8 *frame = Stack.Locals; argn = (Stack.Object && !is_static) ? 1 : 0; // is it a blueprint call ? if (*Stack.Code == EX_EndFunctionParms) { for (UProperty *prop = (UProperty *)function->Children; prop; prop = (UProperty *)prop->Next) { if (prop->PropertyFlags & CPF_ReturnParm) continue; if (!on_error) { PyObject *arg = ue_py_convert_property(prop, (uint8 *)Stack.Locals); if (!arg) { unreal_engine_py_log_error(); on_error = true; } else { PyTuple_SetItem(py_args, argn++, arg); } } } } else { //UE_LOG(LogPython, Warning, TEXT("BLUEPRINT CALL")); frame = (uint8 *)FMemory_Alloca(function->PropertiesSize); FMemory::Memzero(frame, function->PropertiesSize); for (UProperty *prop = (UProperty *)function->Children; *Stack.Code != EX_EndFunctionParms; prop = (UProperty *)prop->Next) { Stack.Step(Stack.Object, prop->ContainerPtrToValuePtr<uint8>(frame)); if (prop->PropertyFlags & CPF_ReturnParm) continue; if (!on_error) { PyObject *arg = ue_py_convert_property(prop, frame); if (!arg) { unreal_engine_py_log_error(); on_error = true; } else { PyTuple_SetItem(py_args, argn++, arg); } } } } Stack.Code++; if (on_error || !function->py_callable) { Py_DECREF(py_args); return; } PyObject *ret = PyObject_CallObject(function->py_callable, py_args); Py_DECREF(py_args); if (!ret) { unreal_engine_py_log_error(); return; } // get return value (if required) UProperty *return_property = function->GetReturnProperty(); if (return_property && function->ReturnValueOffset != MAX_uint16) { #if defined(UEPY_MEMORY_DEBUG) UE_LOG(LogPython, Warning, TEXT("FOUND RETURN VALUE")); #endif if (ue_py_convert_pyobject(ret, return_property, frame)) { // copy value to stack result value FMemory::Memcpy(RESULT_PARAM, frame + function->ReturnValueOffset, return_property->ArrayDim * return_property->ElementSize); } else { UE_LOG(LogPython, Error, TEXT("Invalid return value type for function %s"), *function->GetFName().ToString()); } } Py_DECREF(ret); }