【问题标题】:Iterate through macro defined functions遍历宏定义的函数
【发布时间】:2015-03-24 12:50:25
【问题描述】:

在现有项目中遇到此代码,其中包括在进程中注入 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 ) 

如果只定义了几个函数,那么循环就可以正常工作。但是,当有很多时,编译器似乎不会将代码全部放在一个块中。因此,为什么我们不能通过增加指针来循环它们。

我通过复制函数并声明一个新数组找到了另一种方法,但我宁愿不必在两个文件中维护相同的代码。

项目的一位程序员说他有同样的问题,他通过从项目->属性->c++->优化->禁用中删除项目优化来修复它。

我试过了。也试过project->properties->c++->Code gen->Enable minimum build->No.

我正在使用 vs 2012。

【问题讨论】:

  • 宏不是“函数”。无论您真正在做什么,如果它可以通过七个扩展而不是更少的扩展来重现,请提供一个 真正 七个扩展 oomplete 示例来展示您提到的问题,以及编译器或链接器生成的任何错误消息。或许还要澄清一下“不要把代码全部放在一块”是什么意思。
  • @WhozCraig 感谢您将讨论保持在精英级别。

标签: c++ c-preprocessor


【解决方案1】:

如果您可以简单地将指针放入数组中,这听起来确实会容易得多。除非您遇到不能同时声明函数/类型和填充数组的问题(不能将声明与初始化程序交错,不能将有效语句放在顶层),这意味着这样做会意思是复制函数名列表。

这听起来像是X-macros 的工作。 X 宏本质上是高阶函数的预处理器变体:宏调用是独立于定义宏的上下文形成和保存的。这样就可以更改扩展的宏,或应用多个宏。

例如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]();
    }
}

函数列表只需要维护在一个地方,但是它的included的上下文发生了变化,并且改变了函数声明宏的含义,使其可以重复用于多种用途。

也可以在预处理器中使用“真正的”高阶宏,但这样做需要either a bit of boilerplate or a metaprogramming library,因此虽然它更优雅,但可能不值得为单个元代码而烦恼。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-21
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 2011-08-18
    • 1970-01-01
    • 2022-06-13
    • 1970-01-01
    相关资源
    最近更新 更多