static PyObject *py_ue_uscriptstruct_get_field(ue_PyUScriptStruct *self, PyObject * args) { char *name; int index = 0; if (!PyArg_ParseTuple(args, "s|i:get_field", &name, &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); return ue_py_convert_property(u_property, self->data, index); }
static PyObject *ue_PyUScriptStruct_getattro(ue_PyUScriptStruct *self, PyObject *attr_name) { PyObject *ret = PyObject_GenericGetAttr((PyObject *)self, attr_name); if (!ret) { 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) { // swallow previous exception PyErr_Clear(); return ue_py_convert_property(u_property, self->data, 0); } } } return ret; }
PyObject *py_ue_uscriptstruct_as_dict(ue_PyUScriptStruct * self, PyObject * args) { PyObject *py_bool = nullptr; if (!PyArg_ParseTuple(args, "|O:as_dict", &py_bool)) { return nullptr; } static const FName DisplayNameKey(TEXT("DisplayName")); PyObject *py_struct_dict = PyDict_New(); TFieldIterator<UProperty> SArgs(self->u_struct); for (; SArgs; ++SArgs) { PyObject *struct_value = ue_py_convert_property(*SArgs, self->data, 0); if (!struct_value) { Py_DECREF(py_struct_dict); return NULL; } FString prop_name = SArgs->GetName(); #if WITH_EDITOR if (py_bool && PyObject_IsTrue(py_bool)) { if (SArgs->HasMetaData(DisplayNameKey)) { FString display_name = SArgs->GetMetaData(DisplayNameKey); if (display_name.Len() > 0) prop_name = display_name; } } #endif PyDict_SetItemString(py_struct_dict, TCHAR_TO_UTF8(*prop_name), struct_value); } return py_struct_dict; }
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); }