将指向成员函数的指针转换为intptr_t

时间:2013-09-15 16:30:47

标签: c++ pointers function-pointers member-function-pointers member-functions

问题:有没有办法在C ++中将指向成员函数的指针转换为intptr_t?

已知因素:

  1. 我知道会员功能指针非常特别
  2. 我知道成员函数传递隐藏的“this”参数(__thiscall)。
  3. 我知道sizeof(成员函数指针)> sizeof(intptr_t)在某些情况下, 在这个问题中我只讨论可能的情况,即在我的情况下sizeof(成员函数指针)== sizeof(intptr_t)。
  4. 最后我知道将指针转换为intptr_t并不是一个好的模式。
  5. 示例代码:

    class test // No inheritance, in the case I need
        {
        public:
        void func();    // No virtual, or any special modifiers in the case I need
        };
    
    void main2()
        {
        intptr_t p = &test::func;
        };
    

    我知道有一个变通方法可以做这个演员,但是我不喜欢它,因为它重新出现了一个临时变量:

    void my_way()
        {
        intptr_t p;
        auto t = &test::func;       // Temp variable, I don't like the fact I need to use it, but I have no other way for now
        p = *reinterpret_cast<intptr_t*>(&t);
        };
    

    所以问题是如何将内联技巧作为右值表达式进行内联,没有临时变量(并且没有相同的memcpy)。

    示例:

    reinterpret_cast<??>(???_cast<??>(???_cast<??>( &test::func )))
    

    (我不关心表达的美妙程度)。

    -------------------------(以下是关于为什么而不是问题的一些想法)----------- ---------------------

    这个网站上有一些类似的主题,但是他们都主要谈到“为什么你这样做?”,或者“为什么你需要这个?”,并且谈到这个问题解决了那个问题的人,但不适合我。

    为什么我需要这样的员工:我正在编写某种任务,我决定实现自己的动态链接机制。 可以有几个特定的​​应用程序。

    在我的情况下 - 动态链接机制 - 我想将一个指向函数的指针传递给另一个模块。 我有一个类和一个接口作为一个单独的结构(我知道,有一些libs采用相同的方法)。 已知使用此机制的所有类都是普通的(根本没有继承,所以没有虚拟等)。 所有这些都在MSVC 2012编译的x86 32位或最多64位Windows上运行。 由于接口与类完全隔离,因此它使用指针数组。 Lib将数组传递给主机进程。 在主持人的过程中我有这个...它甚至不是一个“问题”,但仍然是:

    inline int my_interface::func_name(int param)
        {
        decltype(&interface_name::func_name) temp;
        *((intptr_t*)&temp) = reinterpret_cast<interface_name::funcs*>(interface_desc->funcs)->func_name;
        return (reinterpret_cast<decltype(this)>(object)->*temp)(param);
        };
    

    这是一个内联函数,所以我希望它尽可能小,如果有可能我想消除“temp”,因为我不确定编译器是否会正确地消除它,即使是所有优化。

    其他应用(hypotetic): - 如果我想保护我的成员函数所在的内存页面与特定后卫保护,该怎么办? WinAPI为我提供了一种方法,但它需要页面的地址。 对于正常功能这样做没有问题,但是对于成员 - 仅对我描述的WA?还是有办法? - 如果我想在运行时修补图像怎么办?即找到一些const并用另一个替换它? 运行时修补至少有几个原因:2.1动态链接重定位过程,2.2代码混淆。

    这只是为了一个注释 - 读者经常会问“为什么”,我不想讨论为什么,因为在我看来可能会有很多应用程序,所有这些应用程序都不适用于新手,但更多适用于安全人员等...

    我在这里要求不要讨论“为什么这样做?”,“为什么不使用现有的机制来实现dll / boost /其他libs /其他语言?”在这个帖子中。

1 个答案:

答案 0 :(得分:2)

不,规范不允许您将函数指针或成员指针强制转换为intptr_t。这样做的原因是因为您可能需要多个intptr_t的数据来描述它们。例如,gcc上的成员指针是3 intptr_t的长,而MSCV的长度是1到4 intptr_t。其中大部分用于处理虚函数。

在某些旧硬件上(C ++支持),指针实际上也比函数指针小。这种情况发生在小型系统上,您可能只需指向8位内存结构,但程序会加载到16位程序存储空间中。

大多数情况下,您尝试使用的此模式用于创建委托:成员函数指针永久绑定到特定对象。这可以使用2个int指针和包装函数

来完成
struct Delegate
{
    intptr_t   obj;  // I'll use intptr_t here, but often this is void*
    intptr_t   func;
};

// you need one of these for each type of mfp you use
static void callT_Test(intptr_t obj)
{
    T* realObj = reinterpret_cast<T*>(obj);
    realObj->test();
}

// constructing a delegate to call test on t
Delegate d;
d.obj = reinterpret_cast<intptr_t>(&t);
d.func = &callT_Test;
相关问题