Skip to content

Commit 04583a6

Browse files
committed
Added automatically deallocating of pointers and callbacks
- Fixed and extended PythonLog() - Renamed get_address() to get_pointer()
1 parent 2378950 commit 04583a6

9 files changed

+106
-46
lines changed

Diff for: src/core/modules/engine/engine_wrap_python.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ bool CGameTrace::DidHitWorld() const
979979
int CGameTrace::GetEntityIndex() const
980980
{
981981
// TODO: Use a more efficient way
982-
return m_pEnt ? IndexFromPointer(object(CPointer((unsigned long) m_pEnt))) : -1;
982+
return m_pEnt ? IndexFromPointer(object(ptr(new CPointer((unsigned long) m_pEnt)))) : -1;
983983
}
984984

985985

Diff for: src/core/modules/memory/memory_callback.cpp

+16-3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ CCallback::CCallback(object oCallback, Convention_t eConv, tuple args, ReturnTyp
5353
: CFunction(NULL, eConv, args, return_type)
5454
{
5555
m_oCallback = oCallback;
56+
m_bAutoDealloc = true;
5657

5758
// Find the proper callback caller function
5859
void* pCallCallbackFunc = NULL;
@@ -101,6 +102,18 @@ CCallback::CCallback(object oCallback, Convention_t eConv, tuple args, ReturnTyp
101102
m_ulAddr = (unsigned long) a.make();
102103
}
103104

105+
CCallback::~CCallback()
106+
{
107+
if (m_bAutoDealloc)
108+
{
109+
PythonLog(4, "[SP] Automatically deallocating callback at %u.", m_ulAddr);
110+
Dealloc();
111+
112+
// This prevents ~CPointer from calling CPointer::Dealloc() again
113+
m_bAutoDealloc = false;
114+
}
115+
}
116+
104117
int CCallback::GetPopSize()
105118
{
106119
/*
@@ -201,18 +214,18 @@ object CallCallback(CCallback* pCallback, unsigned long ulEBP, unsigned long ulE
201214
case SIGCHAR_ULONGLONG: val = object(GetArgument<unsigned long long>(pCallback, ulEBP, ulECX, i)); break;
202215
case SIGCHAR_FLOAT: val = object(GetArgument<float>(pCallback, ulEBP, ulECX, i)); break;
203216
case SIGCHAR_DOUBLE: val = object(GetArgument<double>(pCallback, ulEBP, ulECX, i)); break;
204-
case SIGCHAR_POINTER: val = object(CPointer(GetArgument<unsigned long>(pCallback, ulEBP, ulECX, i))); break;
217+
case SIGCHAR_POINTER: val = object(ptr(new CPointer(GetArgument<unsigned long>(pCallback, ulEBP, ulECX, i)))); break;
205218
case SIGCHAR_STRING: val = object(GetArgument<const char*>(pCallback, ulEBP, ulECX, i)); break;
206219
default: BOOST_RAISE_EXCEPTION(PyExc_TypeError, "Unknown argument type."); break;
207220
}
208221
arg_list.append(val);
209222
}
210-
arg_list.append(CPointer((unsigned long) ulEBP));
223+
arg_list.append(ptr(new CPointer((unsigned long) ulEBP)));
211224
return eval("lambda func, args: func(*args)")(pCallback->m_oCallback, arg_list);
212225

213226
END_BOOST_PY_NORET()
214227

215-
PythonLog(0, "An exception occured while calling the Python callback. The server will now crash!");
228+
PythonLog(0, "[SP] An exception occured while calling the Python callback. The server will now crash!");
216229

217230
// Throw an exception. We will crash now :(
218231
throw;

Diff for: src/core/modules/memory/memory_callback.h

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class CCallback: public CFunction
6868
{
6969
public:
7070
CCallback(object oCallback, Convention_t eConv, tuple args, ReturnType_t return_type);
71+
virtual ~CCallback();
7172

7273
int GetPopSize();
7374
int GetArgumentOffset(int iIndex);

Diff for: src/core/modules/memory/memory_hooks.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ bool SP_HookHandler(DynamicHooks::HookType_t eHookType, CHook* pHook)
7878
case SIGCHAR_ULONGLONG: retval = GetReturnValue<unsigned long long>(pHook); break;
7979
case SIGCHAR_FLOAT: retval = GetReturnValue<float>(pHook); break;
8080
case SIGCHAR_DOUBLE: retval = GetReturnValue<double>(pHook); break;
81-
case SIGCHAR_POINTER: retval = object(CPointer(pHook->GetReturnValue<unsigned long>())); break;
81+
case SIGCHAR_POINTER: retval = object(ptr(new CPointer(pHook->GetReturnValue<unsigned long>()))); break;
8282
case SIGCHAR_STRING: retval = GetReturnValue<const char *>(pHook); break;
8383
default: BOOST_RAISE_EXCEPTION(PyExc_TypeError, "Unknown type.");
8484
}
@@ -162,7 +162,7 @@ object CStackData::GetItem(unsigned int iIndex)
162162
case SIGCHAR_ULONGLONG: retval = GetArgument<unsigned long long>(m_pHook, iIndex); break;
163163
case SIGCHAR_FLOAT: retval = GetArgument<float>(m_pHook, iIndex); break;
164164
case SIGCHAR_DOUBLE: retval = GetArgument<double>(m_pHook, iIndex); break;
165-
case SIGCHAR_POINTER: retval = object(CPointer(m_pHook->GetArgument<unsigned long>(iIndex))); break;
165+
case SIGCHAR_POINTER: retval = object(ptr(new CPointer(m_pHook->GetArgument<unsigned long>(iIndex)))); break;
166166
case SIGCHAR_STRING: retval = GetArgument<const char *>(m_pHook, iIndex); break;
167167
default: BOOST_RAISE_EXCEPTION(PyExc_TypeError, "Unknown type.") break;
168168
}

Diff for: src/core/modules/memory/memory_hooks.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ class CStackData
2222
public:
2323
CStackData(CHook* pHook);
2424

25-
object GetItem(unsigned int iIndex);
26-
void SetItem(unsigned int iIndex, object value);
25+
object GetItem(unsigned int iIndex);
26+
void SetItem(unsigned int iIndex, object value);
2727

28-
CPointer GetESP()
29-
{ return CPointer((unsigned long) m_pHook->m_pESP); }
28+
CPointer* GetESP()
29+
{ return new CPointer((unsigned long) m_pHook->m_pESP); }
3030

3131
protected:
3232
CHook* m_pHook;

Diff for: src/core/modules/memory/memory_tools.cpp

+18-6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "memory_tools.h"
3737
#include "utility/wrap_macros.h"
3838
#include "utility/sp_util.h"
39+
#include "utility/call_python.h"
3940

4041

4142
DCCallVM* g_pCallVM = dcNewCallVM(4096);
@@ -46,9 +47,19 @@ CHookManager* g_pHookMngr = new CHookManager;
4647
//-----------------------------------------------------------------------------
4748
// CPointer class
4849
//-----------------------------------------------------------------------------
49-
CPointer::CPointer(unsigned long ulAddr /* = 0 */)
50+
CPointer::CPointer(unsigned long ulAddr /* = 0 */, bool bAutoDealloc /* false */)
5051
{
5152
m_ulAddr = ulAddr;
53+
m_bAutoDealloc = bAutoDealloc;
54+
}
55+
56+
CPointer::~CPointer()
57+
{
58+
if (m_bAutoDealloc)
59+
{
60+
PythonLog(4, "[SP] Automatically deallocating pointer at %u.", m_ulAddr);
61+
Dealloc();
62+
}
5263
}
5364

5465
void CPointer::SetStringPtr(char* szText, int iOffset /* = 0 */)
@@ -83,12 +94,13 @@ CPointer* CPointer::GetPtr(int iOffset /* = 0 */)
8394
return new CPointer(*(unsigned long *) (m_ulAddr + iOffset));
8495
}
8596

86-
void CPointer::SetPtr(CPointer* ptr, int iOffset /* = 0 */)
97+
void CPointer::SetPtr(object ptr, int iOffset /* = 0 */)
8798
{
8899
if (!IsValid())
89100
BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Pointer is NULL.")
90-
91-
*(unsigned long *) m_ulAddr = ptr->m_ulAddr;
101+
102+
unsigned long ulAddr = ExtractPyPtr(ptr);
103+
*(unsigned long *) m_ulAddr = m_ulAddr;
92104
}
93105

94106
int CPointer::Compare(object oOther, unsigned long ulNum)
@@ -193,8 +205,8 @@ CFunction* CPointer::MakeVirtualFunction(int iIndex, Convention_t eConv, tuple a
193205
// CFunction class
194206
//-----------------------------------------------------------------------------
195207
CFunction::CFunction(unsigned long ulAddr, Convention_t eConv, tuple args, ReturnType_t return_type)
208+
: CPointer(ulAddr)
196209
{
197-
m_ulAddr = ulAddr;
198210
m_eConv = eConv;
199211
m_Args = args;
200212
m_ReturnType = return_type;
@@ -254,7 +266,7 @@ object CFunction::Call(tuple args, dict kw)
254266
case DC_SIGCHAR_ULONGLONG: return object((unsigned long long) dcCallLongLong(g_pCallVM, m_ulAddr));
255267
case DC_SIGCHAR_FLOAT: return object(dcCallFloat(g_pCallVM, m_ulAddr));
256268
case DC_SIGCHAR_DOUBLE: return object(dcCallDouble(g_pCallVM, m_ulAddr));
257-
case DC_SIGCHAR_POINTER: return object(CPointer(dcCallPointer(g_pCallVM, m_ulAddr)));
269+
case DC_SIGCHAR_POINTER: return object(ptr(new CPointer(dcCallPointer(g_pCallVM, m_ulAddr))));
258270
case DC_SIGCHAR_STRING: return object((const char *) dcCallPointer(g_pCallVM, m_ulAddr));
259271
default: BOOST_RAISE_EXCEPTION(PyExc_TypeError, "Unknown return type.")
260272
}

Diff for: src/core/modules/memory/memory_tools.h

+16-14
Original file line numberDiff line numberDiff line change
@@ -159,26 +159,27 @@ class CFunction;
159159
class CPointer
160160
{
161161
public:
162-
CPointer(unsigned long ulAddr = 0);
162+
CPointer(unsigned long ulAddr = 0, bool bAutoDealloc = false);
163+
virtual ~CPointer();
163164

164165
operator unsigned long() const { return m_ulAddr; }
165166

166167
// Implement some operators
167168
template<class T>
168-
const CPointer operator+(T const& rhs)
169-
{ return CPointer(m_ulAddr + rhs); }
169+
const CPointer* operator+(T const& rhs)
170+
{ return new CPointer(m_ulAddr + rhs); }
170171

171172
template<class T>
172-
const CPointer operator-(T const& rhs)
173-
{ return CPointer(m_ulAddr - rhs); }
173+
const CPointer* operator-(T const& rhs)
174+
{ return new CPointer(m_ulAddr - rhs); }
174175

175176
template<class T>
176-
const CPointer operator+=(T const& rhs)
177-
{ m_ulAddr += rhs; return *this; }
177+
const CPointer* operator+=(T const& rhs)
178+
{ m_ulAddr += rhs; return this; }
178179

179180
template<class T>
180-
const CPointer operator-=(T const& rhs)
181-
{ m_ulAddr -= rhs; return *this; }
181+
const CPointer* operator-=(T const& rhs)
182+
{ m_ulAddr -= rhs; return this; }
182183

183184
bool operator!()
184185
{ return !m_ulAddr; }
@@ -217,7 +218,7 @@ class CPointer
217218
void SetStringArray(char* szText, int iOffset = 0);
218219

219220
CPointer* GetPtr(int iOffset = 0);
220-
void SetPtr(CPointer* ptr, int iOffset = 0);
221+
void SetPtr(object ptr, int iOffset = 0);
221222

222223
bool IsOverlapping(object oOther, unsigned long ulNumBytes);
223224
CPointer* SearchBytes(object oBytes, unsigned long ulNumBytes);
@@ -241,6 +242,7 @@ class CPointer
241242

242243
public:
243244
unsigned long m_ulAddr;
245+
bool m_bAutoDealloc;
244246
};
245247

246248

@@ -315,15 +317,15 @@ inline int GetError()
315317
return dcGetError(g_pCallVM);
316318
}
317319

318-
inline CPointer Alloc(int iSize)
320+
inline CPointer* Alloc(int iSize, bool bAutoDealloc = false)
319321
{
320-
return CPointer((unsigned long) UTIL_Alloc(iSize));
322+
return new CPointer((unsigned long) UTIL_Alloc(iSize), bAutoDealloc);
321323
}
322324

323325
template<class T>
324-
CPointer GetAddress(T* ptr)
326+
CPointer* GetPointer(T* ptr)
325327
{
326-
return CPointer((unsigned long) ptr);
328+
return new CPointer((unsigned long) ptr);
327329
}
328330

329331
#endif // _MEMORY_TOOLS_H

Diff for: src/core/modules/memory/memory_wrap_python.cpp

+22-12
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,12 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(set_ptr_overload, SetPtr, 1, 2)
171171
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(set_string_ptr_overload, SetStringPtr, 1, 2)
172172
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(set_string_array_overload, SetStringArray, 1, 2)
173173

174+
175+
BOOST_PYTHON_FUNCTION_OVERLOADS(alloc_overload, Alloc, 1, 2)
176+
174177
void export_memtools()
175178
{
176-
class_<CPointer>("Pointer", init< optional<unsigned long> >())
179+
class_<CPointer, boost::noncopyable>("Pointer", init< optional<unsigned long, bool> >())
177180
// get/set_<type> methods
178181
EXPOSE_GET_SET_TYPE(bool, bool)
179182
EXPOSE_GET_SET_TYPE(char, char)
@@ -332,15 +335,21 @@ void export_memtools()
332335
.def_readwrite("address",
333336
&CPointer::m_ulAddr
334337
)
338+
339+
.def_readwrite("auto_dealloc",
340+
&CPointer::m_bAutoDealloc
341+
)
335342
;
336343

337344
def("alloc",
338345
Alloc,
339-
"Allocates a memory block.",
340-
args("size")
346+
alloc_overload(
347+
"Allocates a memory block.",
348+
args("size", "auto_dealloc")
349+
)[manage_new_object_policy()]
341350
);
342351

343-
class_<CFunction, bases<CPointer> >("Function", init<unsigned long, Convention_t, tuple, ReturnType_t>())
352+
class_<CFunction, bases<CPointer>, boost::noncopyable >("Function", init<unsigned long, Convention_t, tuple, ReturnType_t>())
344353
.def("__call__",
345354
raw_method(&CFunction::Call),
346355
"Calls the function dynamically."
@@ -469,7 +478,7 @@ void export_dynamichooks()
469478

470479
// Properties
471480
.add_property("esp",
472-
&CStackData::GetESP,
481+
make_function(&CStackData::GetESP, manage_new_object_policy()),
473482
"Stack pointer register."
474483
)
475484
;
@@ -480,7 +489,7 @@ void export_dynamichooks()
480489
//-----------------------------------------------------------------------------
481490
void export_callbacks()
482491
{
483-
class_< CCallback, bases< CFunction > >("Callback", init< object, Convention_t, tuple, ReturnType_t >())
492+
class_< CCallback, bases< CFunction >, boost::noncopyable >("Callback", init< object, Convention_t, tuple, ReturnType_t >())
484493
.def_readwrite("callback",
485494
&CCallback::m_oCallback,
486495
"The Python function that gets called by the C++ callback"
@@ -490,14 +499,15 @@ void export_callbacks()
490499

491500

492501
//-----------------------------------------------------------------------------
493-
// Exposes wrap/get_address/TYPE_SIZES functionality
502+
// Exposes wrap/get_pointer/TYPE_SIZES functionality
494503
//-----------------------------------------------------------------------------
495504
// Use this macro to add the ability to get the address of an object
496-
#define GET_ADDRESS(type) \
497-
def("get_address", \
498-
&GetAddress<type>, \
505+
#define GET_POINTER(type) \
506+
def("get_pointer", \
507+
&GetPointer<type>, \
499508
"Returns the memory address of the given object.", \
500-
args("object") \
509+
args("object"), \
510+
manage_new_object_policy() \
501511
);
502512

503513
// Use this macro to add the ability to get the size of an object
@@ -515,7 +525,7 @@ void export_callbacks()
515525

516526
// Use this macro to call the three macros all at once
517527
#define ADD_ALL(type) \
518-
GET_ADDRESS(type) \
528+
GET_POINTER(type) \
519529
WRAP_POINTER(type) \
520530
ADD_SIZE(type)
521531

Diff for: src/core/utility/call_python.h

+26-4
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,23 @@ using namespace boost::python;
5656
// ----------------------------------------------------------------------------
5757
// Python Logging functions
5858
// ----------------------------------------------------------------------------
59-
inline void PythonLog( const char* szLevel, const char* szMessage )
59+
/*
60+
(-1) message (should always be printed)
61+
(0) critical
62+
(1) exception
63+
(2) warning
64+
(3) info
65+
(4) debug
66+
*/
67+
inline void PythonLog( const char* szLevel, const char* szFormat, ... )
6068
{
69+
// Format the message
70+
char szMessage[2048];
71+
va_list args;
72+
va_start(args, szFormat);
73+
vsprintf(szMessage, szFormat, args);
74+
va_end(args);
75+
6176
// Get the std::string instance of szMessage
6277
std::string szMethod = szLevel;
6378

@@ -70,7 +85,7 @@ inline void PythonLog( const char* szLevel, const char* szMessage )
7085
object oLogModule = import("loggers");
7186

7287
// Get the SPLogger instance
73-
object oLogger = oLogModule.attr("SPLogger");
88+
object oLogger = oLogModule.attr("_SPLogger");
7489

7590
// Get the PyObject instance of the SPLogger
7691
PyObject* poLogger = oLogger.ptr();
@@ -81,15 +96,22 @@ inline void PythonLog( const char* szLevel, const char* szMessage )
8196
END_BOOST_PY()
8297
}
8398

84-
inline void PythonLog( int iLevel, const char* szMessage )
99+
inline void PythonLog( int iLevel, const char* szFormat, ... )
85100
{
101+
// Format the message
102+
char szMessage[2048];
103+
va_list args;
104+
va_start(args, szFormat);
105+
vsprintf(szMessage, szFormat, args);
106+
va_end(args);
107+
86108
BEGIN_BOOST_PY()
87109

88110
// Import the loggers module
89111
object oLogModule = import("loggers");
90112

91113
// Get the SPLogger instance
92-
object oLogger = oLogModule.attr("SPLogger");
114+
object oLogger = oLogModule.attr("_SPLogger");
93115

94116
// Get the PyObject instance of the SPLogger
95117
PyObject* poLogger = oLogger.ptr();

0 commit comments

Comments
 (0)