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

标签 c++ pointers function-pointers pointer-to-member member-functions

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

已知因素:

  1. 我知道成员函数指针很特别
  2. 我知道成员函数传递隐藏的“this”参数 (__thiscall)。
  3. 我知道 sizeof(member function pointer) > sizeof(intptr_t) 在某些情况下, 在这个问题中,我只谈论可能的情况,即在我的情况下 sizeof(member function pointer) == sizeof(intptr_t)。
  4. 最后我知道将指针转换为 intptr_t 不是一个好的模式。

示例代码:

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 )))

(我不在乎表情有多美)

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

这个站点上有一些类似的主题,但它们大多都在谈论“你为什么这样做?”或“你为什么需要这个?”,并且谈论这个可以解决提出问题的人的问题,但不适合我。

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

在我的例子中——动态链接机制——我想将一个指向函数的指针传递给另一个模块。 我有一个类和一个接口(interface)作为一个单独的结构(我知道,有一些库具有相同的方法)。 使用这种机制的所有类都是普通的(根本没有继承,所以没有虚拟等等)。 所有这些都在 MSVC 2012 编译的 x86 32 位或最多 64 位 Windows 上运行。 由于接口(interface)与类完全隔离,它使用一个指针数组。 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?或者有办法吗? - 如果我想在运行时修补图像怎么办? IE。找到一些 const 并将其替换为另一个? 运行时打补丁至少有几个原因:2.1 动态链接重定位过程,2.2 代码混淆。

这只是为了说明 - 读者经常问“为什么”,我不想讨论为什么,因为在我看来可以有很多应用程序,所有这些都不是针对新手的,但更多的是针对安全人员等...

我特此请求不要讨论“为什么这样做?”,“为什么不使用现有的dll/boost/其他库/其他语言的机制?”在这个线程中。

最佳答案

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

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

很多时候,您尝试使用的这种模式用于创建委托(delegate):永久绑定(bind)到特定对象的成员函数指针。这可以通过 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;

关于c++ - 将指向成员函数的指针转换为 intptr_t,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18814722/

相关文章:

c++ - 具有 200GB 可用内存的 Bad Alloc c++

c - 通过指向数组的指针取消引用数组值

golang 为什么比较两个指向结构的变量表现不同?

c++ - 将 "read"行放回文件中

c++ - 将网络字节顺序(大端)转换为小端

c++ - 链接器以什么顺序处理库目录?

c - 有没有更有效的方法在不使用数组的情况下使用指针对整数进行排序?

c++ - 将 std::bind 转换为函数指针

c++ - 向控制台打印时间函数产生 1

C++ 回调数组