创建一个允许轻松创建虚拟函数包装器函数的C++宏

Creating a C++ macro that allows for easy creation of virtual-function wrapper functions

本文关键字:函数 创建 包装 C++ 虚拟 许轻松 一个      更新时间:2023-10-16

我正在为一个旧游戏编写修改,并利用基本的逆向工程来实现我的目标。从本质上讲,我一直在自己的代码中重新创建简单版本的逆向工程游戏结构和界面,将我的解决方案构建为共享对象并将其加载到游戏中。

我目前保持代码简单的解决方案是只在逆向工程接口的"我的版本"中包含我需要的功能,为此,我只需编写如下内容:

class GameManager {
public:
Game* GetGame();
Game* NextGame();
Game* PreviousGame();
int   GameCount();
...
};

然后将函数实现为简单的包装器,这些包装器在虚拟方法表中按索引调用原始函数。这样我只能包含我需要的东西,等等。

其中每个都基本上由SomeType* SomeFunction(int param){ typedef thiscall blabla; call_vfunc(1,this,param); }

我想编写一个宏来自动化此过程,例如#define VFUNC(index, returnType, name, parameters)这样简单易用的东西。

我搞砸了它,并为此进行了几次失败的尝试。最近的一个看起来像这样:

#define VFUNC(index, returnType, name, ...) returnType name(__VA_ARGS__) { return call_vfunc(index, this, ##__VA_ARGS__); }

当函数不带任何参数时,这有效,但问题是一旦我引入参数(例如,编写VFUNC(12, int, someFunction, int someParam),当我只想传递参数的名称时,我最终会传递整个声明。我一直在想一种方法,我可以把(int a,int b,int c(变成(a,b,c(,这样我就可以把它们传递给call_vfunc但到目前为止我什么都没有。

TLDR:我想编写一个宏来自动化创建这些虚拟函数"包装函数"的过程。

谢谢。任何帮助或指导都非常感谢=( 如果我弄清楚了,我会让你了解最新情况。

这是你的宏。

用法:

VFUNC(1, int, foo)
VFUNC_P(1, int, foo, (int,x))
VFUNC_P(1, int, foo, (int,x), (float,y))

实现:

#define CAT(x, y) CAT_(x, y)
#define CAT_(x, y) x##y
#define VA_COUNT(...) VA_COUNT_(__VA_ARGS__, 5, 4, 3, 2, 1,)
#define VA_COUNT_(p5, p4, p3, p2, p1, x, ...) x
#define FOR_EACH(macro, ...) CAT(FOR_EACH_, VA_COUNT(__VA_ARGS__))(macro, __VA_ARGS__)
#define FOR_EACH_1(m, p1                ) m p1
#define FOR_EACH_2(m, p1, p2            ) m p1 , m p2
#define FOR_EACH_3(m, p1, p2, p3        ) m p1 , m p2 , m p3
#define FOR_EACH_4(m, p1, p2, p3, p4    ) m p1 , m p2 , m p3 , m p4
#define FOR_EACH_5(m, p1, p2, p3, p4, p5) m p1 , m p2 , m p3 , m p4 , m p5
#define VFUNC_param_decl(type_, name_) ::std::enable_if_t<1, type_> name_
#define VFUNC_param_use(type_, name_) name_
#define VFUNC(index_, return_type_, name_) 
return_type_ name_() 
{ return call_vfunc(index_, this); }
#define VFUNC_P(index_, return_type_, name_, ...) 
return_type_ name_( FOR_EACH(VFUNC_param_decl, __VA_ARGS__) ) 
{ return call_vfunc(index_, this, FOR_EACH(VFUNC_param_use, __VA_ARGS__)); }

上面提供的简单实现有一些限制:

对于参数
  • 为 0 的函数,有一个单独的宏。
  • 您需要准备O(n)样板宏,其中n是要支持的最大函数参数量。上面的代码最多支持 5 个参数。

有一种方法可以解决这两个问题,但它需要更丑陋的宏。这似乎不值得。


您可以重写这些宏以使用 Boost.Preprocessor 库。(使用BOOST_PP_VARIADIC_TO_SEQ+BOOST_PP_SEQ_FOR_EACH或类似的东西。

它将允许您摆脱样板(因为它将由库提供(。