Repository navigation
Expand file tree
/
Copy pathPythonFunction.cpp
More file actions
129 lines (112 loc) · 3.52 KB
/
Copy pathPythonFunction.cpp
File metadata and controls
129 lines (112 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "UnrealEnginePythonPrivatePCH.h"
#include "PythonFunction.h"
void UPythonFunction::SetPyCallable(PyObject *callable)
{
py_callable = callable;
Py_INCREF(py_callable);
}
#if ENGINE_MINOR_VERSION > 18
void UPythonFunction::CallPythonCallable(UObject *Context, FFrame& Stack, RESULT_DECL)
#else
void UPythonFunction::CallPythonCallable(FFrame& Stack, RESULT_DECL)
#endif
{
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_uobject(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);
}
UPythonFunction::~UPythonFunction()
{
Py_XDECREF(py_callable);
FUnrealEnginePythonHouseKeeper::Get()->UnregisterPyUObject(this);
#if defined(UEPY_MEMORY_DEBUG)
UE_LOG(LogPython, Warning, TEXT("PythonFunction callable %p XDECREF'ed"), this);
#endif
}