Skip to content

Commit 5ad1931

Browse files
author
Roberto De Ioris
committed
another attempt of improving delegates memory management
1 parent a1b8c99 commit 5ad1931

File tree

4 files changed

+115
-65
lines changed

4 files changed

+115
-65
lines changed

Source/UnrealEnginePython/Private/Http/UEPyIHttpRequest.cpp

Lines changed: 90 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33

44
#include "Runtime/Online/HTTP/Public/HttpManager.h"
55

6-
static PyObject *py_ue_ihttp_request_set_verb(ue_PyIHttpRequest *self, PyObject * args) {
6+
static PyObject *py_ue_ihttp_request_set_verb(ue_PyIHttpRequest *self, PyObject * args)
7+
{
78

89
char *verb;
9-
if (!PyArg_ParseTuple(args, "s:set_verb", &verb)) {
10+
if (!PyArg_ParseTuple(args, "s:set_verb", &verb))
11+
{
1012
return NULL;
1113
}
1214

@@ -16,10 +18,12 @@ static PyObject *py_ue_ihttp_request_set_verb(ue_PyIHttpRequest *self, PyObject
1618
return Py_None;
1719
}
1820

19-
static PyObject *py_ue_ihttp_request_set_url(ue_PyIHttpRequest *self, PyObject * args) {
21+
static PyObject *py_ue_ihttp_request_set_url(ue_PyIHttpRequest *self, PyObject * args)
22+
{
2023

2124
char *url;
22-
if (!PyArg_ParseTuple(args, "s:set_url", &url)) {
25+
if (!PyArg_ParseTuple(args, "s:set_url", &url))
26+
{
2327
return NULL;
2428
}
2529

@@ -29,11 +33,13 @@ static PyObject *py_ue_ihttp_request_set_url(ue_PyIHttpRequest *self, PyObject *
2933
return Py_None;
3034
}
3135

32-
static PyObject *py_ue_ihttp_request_set_header(ue_PyIHttpRequest *self, PyObject * args) {
36+
static PyObject *py_ue_ihttp_request_set_header(ue_PyIHttpRequest *self, PyObject * args)
37+
{
3338

3439
char *key;
3540
char *value;
36-
if (!PyArg_ParseTuple(args, "ss:set_header", &key, &value)) {
41+
if (!PyArg_ParseTuple(args, "ss:set_header", &key, &value))
42+
{
3743
return NULL;
3844
}
3945

@@ -43,11 +49,13 @@ static PyObject *py_ue_ihttp_request_set_header(ue_PyIHttpRequest *self, PyObjec
4349
return Py_None;
4450
}
4551

46-
static PyObject *py_ue_ihttp_request_append_to_header(ue_PyIHttpRequest *self, PyObject * args) {
52+
static PyObject *py_ue_ihttp_request_append_to_header(ue_PyIHttpRequest *self, PyObject * args)
53+
{
4754

4855
char *key;
4956
char *value;
50-
if (!PyArg_ParseTuple(args, "ss:append_to_header", &key, &value)) {
57+
if (!PyArg_ParseTuple(args, "ss:append_to_header", &key, &value))
58+
{
5159
return NULL;
5260
}
5361

@@ -57,17 +65,21 @@ static PyObject *py_ue_ihttp_request_append_to_header(ue_PyIHttpRequest *self, P
5765
return Py_None;
5866
}
5967

60-
static PyObject *py_ue_ihttp_request_set_content(ue_PyIHttpRequest *self, PyObject * args) {
68+
static PyObject *py_ue_ihttp_request_set_content(ue_PyIHttpRequest *self, PyObject * args)
69+
{
6170

6271
PyObject *py_obj;
63-
if (!PyArg_ParseTuple(args, "O:set_content", &py_obj)) {
72+
if (!PyArg_ParseTuple(args, "O:set_content", &py_obj))
73+
{
6474
return NULL;
6575
}
6676

67-
if (PyUnicode_Check(py_obj)) {
77+
if (PyUnicode_Check(py_obj))
78+
{
6879
self->http_request->SetContentAsString(UTF8_TO_TCHAR(PyUnicode_AsUTF8(py_obj)));
6980
}
70-
else if (PyBytes_Check(py_obj)) {
81+
else if (PyBytes_Check(py_obj))
82+
{
7183
char *buf = nullptr;
7284
Py_ssize_t len = 0;
7385
PyBytes_AsStringAndSize(py_obj, &buf, &len);
@@ -80,10 +92,12 @@ static PyObject *py_ue_ihttp_request_set_content(ue_PyIHttpRequest *self, PyObje
8092
return Py_None;
8193
}
8294

83-
static PyObject *py_ue_ihttp_request_tick(ue_PyIHttpRequest *self, PyObject * args) {
95+
static PyObject *py_ue_ihttp_request_tick(ue_PyIHttpRequest *self, PyObject * args)
96+
{
8497

8598
float delta_seconds;
86-
if (!PyArg_ParseTuple(args, "f:tick", &delta_seconds)) {
99+
if (!PyArg_ParseTuple(args, "f:tick", &delta_seconds))
100+
{
87101
return NULL;
88102
}
89103

@@ -95,112 +109,129 @@ static PyObject *py_ue_ihttp_request_tick(ue_PyIHttpRequest *self, PyObject * ar
95109
return Py_None;
96110
}
97111

98-
static PyObject *py_ue_ihttp_request_process_request(ue_PyIHttpRequest *self, PyObject * args) {
112+
static PyObject *py_ue_ihttp_request_process_request(ue_PyIHttpRequest *self, PyObject * args)
113+
{
99114
self->http_request->ProcessRequest();
100115

101116
Py_INCREF(Py_None);
102117
return Py_None;
103118
}
104119

105-
static PyObject *py_ue_ihttp_request_cancel_request(ue_PyIHttpRequest *self, PyObject * args) {
120+
static PyObject *py_ue_ihttp_request_cancel_request(ue_PyIHttpRequest *self, PyObject * args)
121+
{
106122
self->http_request->CancelRequest();
107123

108124
Py_INCREF(Py_None);
109125
return Py_None;
110126
}
111127

112-
static PyObject *py_ue_ihttp_request_get_status(ue_PyIHttpRequest *self, PyObject * args) {
128+
static PyObject *py_ue_ihttp_request_get_status(ue_PyIHttpRequest *self, PyObject * args)
129+
{
113130
return PyLong_FromLong((int)self->http_request->GetStatus());
114131
}
115132

116-
static PyObject *py_ue_ihttp_request_get_verb(ue_PyIHttpRequest *self, PyObject * args) {
133+
static PyObject *py_ue_ihttp_request_get_verb(ue_PyIHttpRequest *self, PyObject * args)
134+
{
117135
return PyUnicode_FromString(TCHAR_TO_UTF8(*self->http_request->GetVerb()));
118136
}
119137

120-
static PyObject *py_ue_ihttp_request_get_elapsed_time(ue_PyIHttpRequest *self, PyObject * args) {
138+
static PyObject *py_ue_ihttp_request_get_elapsed_time(ue_PyIHttpRequest *self, PyObject * args)
139+
{
121140
return PyFloat_FromDouble(self->http_request->GetElapsedTime());
122141
}
123142

124-
static PyObject *py_ue_ihttp_request_get_response(ue_PyIHttpRequest *self, PyObject * args) {
143+
static PyObject *py_ue_ihttp_request_get_response(ue_PyIHttpRequest *self, PyObject * args)
144+
{
125145
FHttpResponsePtr response = self->http_request->GetResponse();
126-
if (!response.IsValid()) {
146+
if (!response.IsValid())
147+
{
127148
return PyErr_Format(PyExc_Exception, "unable to retrieve IHttpResponse");
128149
}
129150
return py_ue_new_ihttp_response(response.Get());
130151
}
131152

132-
void UPythonHttpDelegate::OnRequestComplete(FHttpRequestPtr request, FHttpResponsePtr response, bool successful) {
153+
void FPythonSmartHttpDelegate::OnRequestComplete(FHttpRequestPtr request, FHttpResponsePtr response, bool successful)
154+
{
133155
FScopePythonGIL gil;
134156

135-
if (!request.IsValid() || !response.IsValid()) {
157+
if (!request.IsValid() || !response.IsValid())
158+
{
136159
UE_LOG(LogPython, Error, TEXT("Unable to retrieve HTTP infos"));
137160
return;
138161
}
139162

140163
PyObject *ret = PyObject_CallFunction(py_callable, (char *)"OOO", py_http_request, py_ue_new_ihttp_response(response.Get()), successful ? Py_True : Py_False);
141-
if (!ret) {
164+
if (!ret)
165+
{
142166
unreal_engine_py_log_error();
143167
return;
144168
}
145169
Py_DECREF(ret);
146170
}
147171

148-
void UPythonHttpDelegate::OnRequestProgress(FHttpRequestPtr request, int32 sent, int32 received) {
172+
void FPythonSmartHttpDelegate::OnRequestProgress(FHttpRequestPtr request, int32 sent, int32 received)
173+
{
149174
FScopePythonGIL gil;
150175

151-
if (!request.IsValid()) {
176+
if (!request.IsValid())
177+
{
152178
UE_LOG(LogPython, Error, TEXT("Unable to retrieve HTTP infos"));
153179
return;
154180
}
155181

156182
PyObject *ret = PyObject_CallFunction(py_callable, (char *)"Oii", py_http_request, sent, received);
157-
if (!ret) {
183+
if (!ret)
184+
{
158185
unreal_engine_py_log_error();
159186
return;
160187
}
161188
Py_DECREF(ret);
162189
}
163190

164-
static PyObject *py_ue_ihttp_request_bind_on_process_request_complete(ue_PyIHttpRequest *self, PyObject * args) {
191+
static PyObject *py_ue_ihttp_request_bind_on_process_request_complete(ue_PyIHttpRequest *self, PyObject * args)
192+
{
165193

166194
PyObject *py_callable;
167-
if (!PyArg_ParseTuple(args, "O:bind_on_process_request_complete", &py_callable)) {
168-
return NULL;
195+
if (!PyArg_ParseTuple(args, "O:bind_on_process_request_complete", &py_callable))
196+
{
197+
return nullptr;
169198
}
170199

171-
if (!PyCallable_Check(py_callable)) {
200+
if (!PyCallable_Check(py_callable))
201+
{
172202
return PyErr_Format(PyExc_Exception, "argument is not a callable");
173203
}
174204

175-
UPythonHttpDelegate *py_delegate = NewObject<UPythonHttpDelegate>();
205+
TSharedRef<FPythonSmartHttpDelegate> py_delegate = MakeShareable(new FPythonSmartHttpDelegate);
176206
py_delegate->SetPyCallable(py_callable);
177207
// this trick avoids generating a new python object
178208
py_delegate->SetPyHttpRequest(self);
179-
self->http_request->OnProcessRequestComplete().BindUObject(py_delegate, &UPythonHttpDelegate::OnRequestComplete);
209+
self->http_request->OnProcessRequestComplete().BindSP(py_delegate, &FPythonSmartHttpDelegate::OnRequestComplete);
180210

181-
Py_INCREF(Py_None);
182-
return Py_None;
211+
Py_RETURN_NONE;
183212
}
184213

185-
static PyObject *py_ue_ihttp_request_bind_on_request_progress(ue_PyIHttpRequest *self, PyObject * args) {
214+
static PyObject *py_ue_ihttp_request_bind_on_request_progress(ue_PyIHttpRequest *self, PyObject * args)
215+
{
186216

187217
PyObject *py_callable;
188-
if (!PyArg_ParseTuple(args, "O:bind_on_request_progress", &py_callable)) {
189-
return NULL;
218+
if (!PyArg_ParseTuple(args, "O:bind_on_request_progress", &py_callable))
219+
{
220+
return nullptr;
190221
}
191222

192-
if (!PyCallable_Check(py_callable)) {
223+
if (!PyCallable_Check(py_callable))
224+
{
193225
return PyErr_Format(PyExc_Exception, "argument is not a callable");
194226
}
195227

196-
UPythonHttpDelegate *py_delegate = NewObject<UPythonHttpDelegate>();
228+
TSharedRef<FPythonSmartHttpDelegate> py_delegate = MakeShareable(new FPythonSmartHttpDelegate);
197229
py_delegate->SetPyCallable(py_callable);
198230
// this trick avoids generating a new python object
199231
py_delegate->SetPyHttpRequest(self);
200-
self->http_request->OnRequestProgress().BindUObject(py_delegate, &UPythonHttpDelegate::OnRequestProgress);
232+
self->http_request->OnRequestProgress().BindSP(py_delegate, &FPythonSmartHttpDelegate::OnRequestProgress);
201233

202-
Py_INCREF(Py_None);
203-
return Py_None;
234+
Py_RETURN_NONE;
204235
}
205236

206237
static PyMethodDef ue_PyIHttpRequest_methods[] = {
@@ -228,12 +259,13 @@ static PyObject *ue_PyIHttpRequest_str(ue_PyIHttpRequest *self)
228259
&self->http_request.Get());
229260
}
230261

231-
static void ue_PyIHttpRequest_dealloc(ue_PyIHttpRequest *self) {
262+
static void ue_PyIHttpRequest_dealloc(ue_PyIHttpRequest *self)
263+
{
232264
#if defined(UEPY_MEMORY_DEBUG)
233-
UE_LOG(LogPython, Warning, TEXT("Destroying ue_PyIHttpRequest %p mapped to IHttpRequest %p"), self, &self->http_request.Get());
265+
UE_LOG(LogPython, Warning, TEXT("Destroying ue_PyIHttpRequest %p mapped to IHttpRequest %p"), self, &self->http_request.Get());
234266
#endif
235267
Py_DECREF(self->py_dict);
236-
Py_TYPE(self)->tp_free((PyObject *)self);
268+
Py_TYPE(self)->tp_free((PyObject *)self);
237269
}
238270

239271
static PyTypeObject ue_PyIHttpRequestType = {
@@ -269,36 +301,41 @@ static PyTypeObject ue_PyIHttpRequestType = {
269301
0,
270302
};
271303

272-
static int ue_py_ihttp_request_init(ue_PyIHttpRequest *self, PyObject *args, PyObject *kwargs) {
304+
static int ue_py_ihttp_request_init(ue_PyIHttpRequest *self, PyObject *args, PyObject *kwargs)
305+
{
273306
char *verb = nullptr;
274307
char* url = nullptr;
275-
if (!PyArg_ParseTuple(args, "|ss:__init__", &verb, &url)) {
308+
if (!PyArg_ParseTuple(args, "|ss:__init__", &verb, &url))
309+
{
276310
return -1;
277311
}
278312
new(&self->http_request) TSharedRef<IHttpRequest>(FHttpModule::Get().CreateRequest());
279313
self->py_dict = PyDict_New();
280-
if (verb) {
314+
if (verb)
315+
{
281316
self->http_request->SetVerb(UTF8_TO_TCHAR(verb));
282317
}
283318

284-
if (url) {
319+
if (url)
320+
{
285321
self->http_request->SetURL(UTF8_TO_TCHAR(url));
286322
}
287323

288324
self->base.http_base = &self->http_request.Get();
289325
return 0;
290326
}
291327

292-
void ue_python_init_ihttp_request(PyObject *ue_module) {
328+
void ue_python_init_ihttp_request(PyObject *ue_module)
329+
{
293330
ue_PyIHttpRequestType.tp_new = PyType_GenericNew;
294331

295332
ue_PyIHttpRequestType.tp_init = (initproc)ue_py_ihttp_request_init;
296333

297334
ue_PyIHttpRequestType.tp_base = &ue_PyIHttpBaseType;
298335

299336
ue_PyIHttpRequestType.tp_getattro = PyObject_GenericGetAttr;
300-
ue_PyIHttpRequestType.tp_setattro = PyObject_GenericSetAttr;
301-
ue_PyIHttpRequestType.tp_dictoffset = offsetof(ue_PyIHttpRequest, py_dict);
337+
ue_PyIHttpRequestType.tp_setattro = PyObject_GenericSetAttr;
338+
ue_PyIHttpRequestType.tp_dictoffset = offsetof(ue_PyIHttpRequest, py_dict);
302339

303340
if (PyType_Ready(&ue_PyIHttpRequestType) < 0)
304341
return;

Source/UnrealEnginePython/Private/Http/UEPyIHttpRequest.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
#include "Runtime/Online/HTTP/Public/Interfaces/IHttpRequest.h"
66
#include "Runtime/Online/HTTP/Public/HttpModule.h"
77

8-
#include "UEPyIHttpRequest.generated.h"
9-
108

119
extern PyTypeObject ue_PyIHttpBaseType;
1210

@@ -20,10 +18,8 @@ typedef struct {
2018

2119
void ue_python_init_ihttp_request(PyObject *);
2220

23-
UCLASS()
24-
class UPythonHttpDelegate : public UPythonDelegate
21+
class FPythonSmartHttpDelegate : public FPythonSmartDelegate
2522
{
26-
GENERATED_BODY()
2723

2824
public:
2925
void OnRequestComplete(FHttpRequestPtr request, FHttpResponsePtr response, bool successful);
@@ -34,7 +30,7 @@ class UPythonHttpDelegate : public UPythonDelegate
3430
Py_INCREF(py_http_request);
3531
}
3632

37-
~UPythonHttpDelegate() {
33+
~FPythonSmartHttpDelegate() {
3834
Py_XDECREF(py_http_request);
3935
}
4036
protected:

0 commit comments

Comments
 (0)