Skip to content

Commit 982bb63

Browse files
committed
VTHook: add void return type support
1 parent 6d64ba2 commit 982bb63

1 file changed

Lines changed: 33 additions & 33 deletions

File tree

include/dynlibutils/vthook.hpp

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,17 @@ class CVTHook : public CMemory
111111
// to the original implementation’s logic. For example, in your hooked method body,
112112
// you can call `hookInstance.Call(...);` to execute the original virtual method with
113113
// the supplied arguments. If not called in the hook, the original logic will not run.
114-
R Call(Args... args) const { return GetOrigin<Function_t>()(args...); }
114+
R Call(Args... args) const
115+
{
116+
if constexpr (std::is_void_v<R>)
117+
{
118+
GetOrigin<Function_t>()(args...);
119+
120+
return;
121+
}
122+
123+
return GetOrigin<Function_t>()(args...);
124+
}
115125

116126
protected: // Implementation methods.
117127
void HookImpl(Function_t pfnTarget) noexcept
@@ -174,24 +184,28 @@ class CVTFHook : public CVTHook<R, Args...>
174184
inline static Function_t sm_callback;
175185
}; // class CVTFHook<R, Args...>
176186

177-
// A template class represents generic manager for multiple virtual‐table hooks of the same signature.
178-
// Template Parameter:
179-
// T — A hook element type, which must:
187+
// A template class represents a generic manager for multiple virtual-table hooks of the same signature.
188+
// Template Parameters:
189+
// TH - A hook element template (e.g., CVTHook or CVTFHook).
190+
// R - Return type of the virtual method.
191+
// C - Pointer type of the class instance (this pointer).
192+
// Args - Remaining argument types.
193+
// Hook element type must:
180194
// * Define a nested alias Function_t (e.g., R(*)(Args...)).
181195
// * Provide methods:
182196
// - void Hook(CVirtualTable, std::ptrdiff_t, Function_t)
183197
// - R Call(C*, Args...) (or similar overloads)
184198
// - bool Unhook(), etc.
185-
// Typical instantiations might be CVTHook<R,Args...> or CVTFHook<R,Args...>.
186-
template<class T>
199+
// Typical instantiations might be CVTHook<R, Args...> or CVTFHook<R, Args...>.
200+
template<template<typename, typename...> class TH, typename R, typename C, typename ...Args>
187201
class CVTMHookBase
188202
{
189203
public:
190204
CVTMHookBase() = default;
191205
CVTMHookBase(const CVTMHookBase &other) = delete;
192206
CVTMHookBase(CVTMHookBase &&other) = default;
193207

194-
using Element_t = T;
208+
using Element_t = TH<R, C, Args...>;
195209
using Function_t = typename Element_t::Function_t;
196210

197211
public:
@@ -219,22 +233,28 @@ class CVTMHookBase
219233
return m_storage.emplace(pVTable, std::move(vth));
220234
}
221235

222-
template<typename R, typename C, typename ...Args>
223236
R Call(C pThis, Args... args)
224237
{
225238
auto found = Find(CVirtualTable(pThis));
226239

227240
assert(found.first != found.second);
228241

242+
if constexpr (std::is_void_v<R>)
243+
{
244+
found.first->second.Call(pThis, args...);
245+
246+
return;
247+
}
248+
229249
return found.first->second.Call(pThis, args...);
230250
}
231251

232252
// Returns a vector containing the return values from each hook’s Call() invocation,
233253
// in order of insertion. If no hooks were found for that vtable, returns an empty vector.
234-
template<typename R, typename C, typename ...Args>
235-
std::vector<R> CallAll(C pThis, Args... args)
254+
template<typename Ret = R, typename = std::enable_if_t<!std::is_void_v<Ret>>>
255+
std::vector<Ret> CallAll(C pThis, Args... args)
236256
{
237-
std::vector<R> results;
257+
std::vector<Ret> results;
238258

239259
auto found = Find(CVirtualTable(pThis));
240260

@@ -250,36 +270,16 @@ class CVTMHookBase
250270
return results;
251271
}
252272

253-
// Returns true if at least one hook was executed; false if no hooks were found for that vtable.
254-
template<typename C, typename ...Args>
255-
bool CallAllNoReturn(C pThis, Args... args)
256-
{
257-
auto found = Find(CVirtualTable(pThis));
258-
259-
if (found.first == found.second)
260-
{
261-
return false;
262-
}
263-
264-
// results.reserve(vhooks.size());
265-
266-
for (auto it = found.first; it != found.second; it++)
267-
{
268-
it->second.Call(pThis, args...);
269-
}
270-
271-
return true;
272-
}
273273
// erases all hook elements associated with that vtable.
274274
// - Returns the number of elements removed (std::size_t).
275275
std::size_t RemoveHook(CVirtualTable pVTable) { return m_storage.erase(pVTable); }
276276

277277
private:
278278
std::multimap<CVirtualTable, Element_t> m_storage;
279-
}; // class CVTMHookBase<T, FUNC>
279+
}; // class CVTMHookBase<TH, R, C, Args...>
280280

281281
template<typename R, typename ...Args>
282-
using CVTMHook = CVTMHookBase<CVTHook<R, Args...>>;
282+
using CVTMHook = CVTMHookBase<CVTHook, R, Args...>;
283283

284284
// A template class manages multiple virtual‐table hooks per class instance, where each hook can
285285
// execute multiple callbacks (std::function) when the original virtual method is invoked.

0 commit comments

Comments
 (0)