3131#include < string>
3232
3333#include " dyncall.h"
34- #include " dyncall_signature.h"
3534
3635#include " memory_hooks.h"
3736#include " memory_tools.h"
@@ -177,49 +176,47 @@ CPointer* CPointer::GetVirtualFunc(int iIndex)
177176 return new CPointer ((unsigned long ) vtable[iIndex]);
178177}
179178
180- CFunction* CPointer::MakeFunction (Convention_t eConv, char * szParams )
179+ CFunction* CPointer::MakeFunction (Convention_t eConv, tuple args, ReturnType_t return_type )
181180{
182181 if (!IsValid ())
183182 BOOST_RAISE_EXCEPTION (PyExc_ValueError, " Pointer is NULL." )
184183
185- return new CFunction (m_ulAddr, eConv, szParams );
184+ return new CFunction (m_ulAddr, eConv, args, return_type );
186185}
187186
188- CFunction* CPointer::MakeVirtualFunction (int iIndex, Convention_t eConv, char * szParams )
187+ CFunction* CPointer::MakeVirtualFunction (int iIndex, Convention_t eConv, tuple args, ReturnType_t return_type )
189188{
190- return GetVirtualFunc (iIndex)->MakeFunction (eConv, szParams );
189+ return GetVirtualFunc (iIndex)->MakeFunction (eConv, args, return_type );
191190}
192191
193192// -----------------------------------------------------------------------------
194193// CFunction class
195194// -----------------------------------------------------------------------------
196- CFunction::CFunction (unsigned long ulAddr, Convention_t eConv, char * szParams )
195+ CFunction::CFunction (unsigned long ulAddr, Convention_t eConv, tuple args, ReturnType_t return_type )
197196{
198197 m_ulAddr = ulAddr;
199198 m_eConv = eConv;
200- m_szParams = strdup (szParams);
199+ m_Args = args;
200+ m_ReturnType = return_type;
201201}
202202
203203object CFunction::Call (tuple args, dict kw)
204- {
204+ {
205205 if (!IsValid ())
206206 BOOST_RAISE_EXCEPTION (PyExc_ValueError, " Function pointer is NULL." )
207207
208+ if (len (args) != len (m_Args))
209+ BOOST_RAISE_EXCEPTION (PyExc_ValueError, " Number of passed arguments is not equal to the required number." )
210+
211+ // Reset VM and set the calling convention
208212 dcReset (g_pCallVM);
209213 dcMode (g_pCallVM, GetDynCallConvention (m_eConv));
210- char * ptr = (char *) m_szParams;
211- int pos = 0 ;
212- char ch;
213- while ((ch = *ptr) != ' \0 ' && ch != ' )' )
214- {
215- if (ch == DC_SIGCHAR_VOID)
216- {
217- ptr++;
218- break ;
219- }
220214
221- object arg = args[pos];
222- switch (ch)
215+ // Loop through all passed arguments and add them to the VM
216+ for (int i=0 ; i < len (args); i++)
217+ {
218+ object arg = args[i];
219+ switch (extract<Argument_t>(m_Args[i]))
223220 {
224221 case DC_SIGCHAR_BOOL: dcArgBool (g_pCallVM, extract<bool >(arg)); break ;
225222 case DC_SIGCHAR_CHAR: dcArgChar (g_pCallVM, extract<char >(arg)); break ;
@@ -236,20 +233,14 @@ object CFunction::Call(tuple args, dict kw)
236233 case DC_SIGCHAR_DOUBLE: dcArgDouble (g_pCallVM, extract<double >(arg)); break ;
237234 case DC_SIGCHAR_POINTER: dcArgPointer (g_pCallVM, ExtractPyPtr (arg)); break ;
238235 case DC_SIGCHAR_STRING: dcArgPointer (g_pCallVM, (unsigned long ) (void *) extract<char *>(arg)); break ;
239- default : BOOST_RAISE_EXCEPTION (PyExc_ValueError, " Unknown parameter type." )
236+ default : BOOST_RAISE_EXCEPTION (PyExc_ValueError, " Unknown argument type." )
240237 }
241- pos++; ptr++;
242238 }
243239
244- if (pos != len (args))
245- BOOST_RAISE_EXCEPTION (PyExc_ValueError, " String parameter count does not equal with length of tuple." )
246-
247- if (ch == ' \0 ' )
248- BOOST_RAISE_EXCEPTION (PyExc_ValueError, " String parameter has no return type." )
249-
250- switch (*++ptr)
240+ // Call the function
241+ switch (m_ReturnType)
251242 {
252- case DC_SIGCHAR_VOID: dcCallVoid (g_pCallVM, m_ulAddr); break ;
243+ case DC_SIGCHAR_VOID: dcCallVoid (g_pCallVM, m_ulAddr); break ;
253244 case DC_SIGCHAR_BOOL: return object (dcCallBool (g_pCallVM, m_ulAddr));
254245 case DC_SIGCHAR_CHAR: return object (dcCallChar (g_pCallVM, m_ulAddr));
255246 case DC_SIGCHAR_UCHAR: return object ((unsigned char ) dcCallChar (g_pCallVM, m_ulAddr));
@@ -279,18 +270,29 @@ object CFunction::CallTrampoline(tuple args, dict kw)
279270 if (!pHook)
280271 BOOST_RAISE_EXCEPTION (PyExc_ValueError, " Function was not hooked." )
281272
282- return CFunction ((unsigned long ) pHook->m_pTrampoline , m_eConv, m_szParams ).Call (args, kw);
273+ return CFunction ((unsigned long ) pHook->m_pTrampoline , m_eConv, m_Args, m_ReturnType ).Call (args, kw);
283274}
284275
285- PyObject* CFunction::AddHook (DynamicHooks::HookType_t eType, PyObject* pCallable)
276+ handle<> CFunction::AddHook (DynamicHooks::HookType_t eType, PyObject* pCallable)
286277{
287278 if (!IsValid ())
288279 BOOST_RAISE_EXCEPTION (PyExc_ValueError, " Function pointer is NULL." )
289280
290- CHook* pHook = g_pHookMngr->HookFunction ((void *) m_ulAddr, m_eConv, m_szParams);
281+ // Generate the argument string
282+ char * szParams = extract<char *>(eval (" lambda args, ret: ''.join(map(chr, args)) + ')' + chr(ret)" )(m_Args, m_ReturnType));
283+ puts (szParams);
284+
285+ // Hook the function
286+ CHook* pHook = g_pHookMngr->HookFunction ((void *) m_ulAddr, m_eConv, strdup (szParams));
287+
288+ // Add the hook handler. If it's already added, it won't be added twice
291289 pHook->AddCallback (eType, (void *) &SP_HookHandler);
290+
291+ // Add the callback to our map
292292 g_mapCallbacks[pHook][eType].push_back (pCallable);
293- return pCallable;
293+
294+ // Return the callback, so we can use this method as a decorator
295+ return handle<>(borrowed (pCallable));
294296}
295297
296298void CFunction::RemoveHook (DynamicHooks::HookType_t eType, PyObject* pCallable)
0 commit comments