遍历宏定义的函数
Iterate through macro defined functions
在现有项目中遇到此代码,该项目包括在进程中注入 DLL 并从那里进行操作。
他们声明了一些函数指针偏移量,然后遍历它们以向其添加特定的 dll 偏移量。
我在遍历宏定义函数时遇到问题。如果我只有 5-6 个函数,它似乎工作正常,但是当我添加更多时它不起作用。
#pragma optimize ( "", off )
#define DLLOFFSET(a1,b1) ((DLLNO_##a1)|((b1)<<8))
#define FUNCPTR(d1,v1,t1,t2,o1) typedef t1 d1##_##v1##_t t2; d1##_##v1##_t *d1##_##v1 = (d1##_##v1##_t *)DLLOFFSET(d1,o1);
#define ASMPTR(d1,v1,o1) DWORD d1##_##v1 = DLLOFFSET(d1,o1);
#define _PTRS_START PREFIX1_aaa
...
FUNCPTR(PREFIX1, aaa, ....., 0xFFFFF)
...
FUNCPTR(PREFIX3, fff, ....., 0xFFFFF)
...
FUNCPTR(PREFIX2, ggg, ....., 0xFFFFF)
...
ASMPTR(PREFIX1, jjj, 0xFFFFF)
...
#define _PTRS_END PREFIX1_jjj
void DefineOffsets()
{
DWORD *p = (DWORD *)&_PTRS_START;
do {
*p = "call update pointer function here"
} while(++p <= (DWORD *)&_PTRS_END);
}
#pragma optimize( "", on )
如果只定义了几个函数,循环就可以正常工作。但是,当有很多时,编译器似乎不会将代码全部放在一个块中。这就是为什么我们不能通过递增指针来循环它们。
我通过复制函数并声明一个新数组找到了另一种方法,但我不想在两个文件中维护相同的代码。
projet 的一位程序员说他遇到了同样的问题,他通过从项目-> 属性->c++->优化->禁用中删除项目优化来修复它。
我试过了。还尝试了项目->属性->c++->代码生成->启用最小构建->否。
我使用的是 vs 2012。
如果您可以简单地将指针放入数组中,这听起来确实会容易得多。除非你遇到不能同时声明 functions/types 和填充数组的问题(不能将声明与初始值设定项交错,不能在顶层放置有效的语句),这意味着要做这意味着复制函数名称列表。
这听起来像是 X-macros 的工作。 X-macros 本质上是高阶函数的预处理器变体:宏调用的形成和保存与宏定义的上下文分开。这使得更改扩展的宏或应用多个宏成为可能。
例如functions.h
:
FUNCTION(void, f1, puts("in f1"))
FUNCTION(void, f2, puts("in f2"))
FUNCTION(void, f3, puts("in f3"))
FUNCTION(void, f4, puts("in f4"))
FUNCTION(void, f5, puts("in f5"))
main.c
:
#define FUNCTION(T, N, B) T N (void){ B; }
#include "functions.h"
#undef FUNCTION
#define FUNCTION(T, N, B) (fptr)N,
typedef void(*fptr)(void);
fptr funcs[] = {
#include "functions.h"
};
int main(void) {
for (int i = 0; i < 5; i ++) {
funcs[i]();
}
}
函数列表只需要在一个地方维护,但是它include
d 的上下文发生了变化,并且改变了函数声明宏的含义,以便它可以重复用于多种用途。
也可以在预处理器中使用 "true" 高阶宏,但这样做需要 either a bit of boilerplate or a metaprogramming library,因此虽然它更优雅,但可能不值得为单个一段元代码。
在现有项目中遇到此代码,该项目包括在进程中注入 DLL 并从那里进行操作。
他们声明了一些函数指针偏移量,然后遍历它们以向其添加特定的 dll 偏移量。
我在遍历宏定义函数时遇到问题。如果我只有 5-6 个函数,它似乎工作正常,但是当我添加更多时它不起作用。
#pragma optimize ( "", off )
#define DLLOFFSET(a1,b1) ((DLLNO_##a1)|((b1)<<8))
#define FUNCPTR(d1,v1,t1,t2,o1) typedef t1 d1##_##v1##_t t2; d1##_##v1##_t *d1##_##v1 = (d1##_##v1##_t *)DLLOFFSET(d1,o1);
#define ASMPTR(d1,v1,o1) DWORD d1##_##v1 = DLLOFFSET(d1,o1);
#define _PTRS_START PREFIX1_aaa
...
FUNCPTR(PREFIX1, aaa, ....., 0xFFFFF)
...
FUNCPTR(PREFIX3, fff, ....., 0xFFFFF)
...
FUNCPTR(PREFIX2, ggg, ....., 0xFFFFF)
...
ASMPTR(PREFIX1, jjj, 0xFFFFF)
...
#define _PTRS_END PREFIX1_jjj
void DefineOffsets()
{
DWORD *p = (DWORD *)&_PTRS_START;
do {
*p = "call update pointer function here"
} while(++p <= (DWORD *)&_PTRS_END);
}
#pragma optimize( "", on )
如果只定义了几个函数,循环就可以正常工作。但是,当有很多时,编译器似乎不会将代码全部放在一个块中。这就是为什么我们不能通过递增指针来循环它们。
我通过复制函数并声明一个新数组找到了另一种方法,但我不想在两个文件中维护相同的代码。
projet 的一位程序员说他遇到了同样的问题,他通过从项目-> 属性->c++->优化->禁用中删除项目优化来修复它。
我试过了。还尝试了项目->属性->c++->代码生成->启用最小构建->否。
我使用的是 vs 2012。
如果您可以简单地将指针放入数组中,这听起来确实会容易得多。除非你遇到不能同时声明 functions/types 和填充数组的问题(不能将声明与初始值设定项交错,不能在顶层放置有效的语句),这意味着要做这意味着复制函数名称列表。
这听起来像是 X-macros 的工作。 X-macros 本质上是高阶函数的预处理器变体:宏调用的形成和保存与宏定义的上下文分开。这使得更改扩展的宏或应用多个宏成为可能。
例如functions.h
:
FUNCTION(void, f1, puts("in f1"))
FUNCTION(void, f2, puts("in f2"))
FUNCTION(void, f3, puts("in f3"))
FUNCTION(void, f4, puts("in f4"))
FUNCTION(void, f5, puts("in f5"))
main.c
:
#define FUNCTION(T, N, B) T N (void){ B; }
#include "functions.h"
#undef FUNCTION
#define FUNCTION(T, N, B) (fptr)N,
typedef void(*fptr)(void);
fptr funcs[] = {
#include "functions.h"
};
int main(void) {
for (int i = 0; i < 5; i ++) {
funcs[i]();
}
}
函数列表只需要在一个地方维护,但是它include
d 的上下文发生了变化,并且改变了函数声明宏的含义,以便它可以重复用于多种用途。
也可以在预处理器中使用 "true" 高阶宏,但这样做需要 either a bit of boilerplate or a metaprogramming library,因此虽然它更优雅,但可能不值得为单个一段元代码。