c++ - 在用 C++ 编写 win32 api 包装器时,如何将此指针传递给静态函数

标签 c++ winapi function pointers

我想将函数对象转换为函数。

我写了这段代码,但它不起作用。

#include <iostream>

typedef int (*int_to_int)(int);

struct adder {
    int n_;
    adder (int n) : n_(n) {}
    int operator() (int x) { return x + n_; }
    operator int_to_int () {
        return this->*&adder::operator();
    }
};

int main(void) {
    adder add_two(2);
    int_to_int add_fn = add_two;
    std::cout << add_two(3) << std::endl; // expect 5
    std::cout << add_fn(3)  << std::endl; // expect 5
    add_fn = adder(5);
    std::cout << add_fn(3)  << std::endl; // expect 8
    return 0;
}

我收到来自 g++ 的消息,说 invalid use of non-static member function

如何获取指向实例成员函数的指针?

编辑:我原来的问题是关于 Win32 API。

我在学校被迫使用旧的 Win32 API 编写 Windows 程序。但我不想像文本上的一些示例代码那样编写可怕的 switch 语句。然后,我决定用 C++ 编写包装器。

我想把窗口类写成...

class Window {
public:
    LRESULT update (HWND, UINT, WPARAM, LPARAM);
    void run();
    // below methods are called by update()
    virtual void onclick(int, int);
    virtual void ondraw(); // ... and more methods
};

并且我愿意通过派生此类并重载一些方法来编写我的应用程序类。

最后,我真正的问题是如何在 C++ 中做到这一点。

 // on initializing my window object,
 // I must register window class with callback which is 
 // not a C++ function object.
 // I try to explain what I want to do with psudocode mixing C++ and javascript.
 WNDCLASS wndclass;
 Window *self = this;
 wndclass.lpfnWndProc = function () {
     return self.update.apply(self, argunemts);
 };

换句话说,我必须将闭包变成函数指针。我不知道该怎么做,但我不敢相信这不能用 C++ 实现。

编辑:这个问题的原标题是如何获取实例成员函数的指针。但是这个标题和我的问题并没有充分说明我的实际问题。对早期的回答者和 litb 表示抱歉,感谢您的建议和非常有用的答案!

最佳答案

更新:您告诉我们您想要什么。我在 SO 上发现了这个问题:Best method for storing this pointer for use in WndProc .我不是 Windows 程序员,但 Adam Rosenfield 的人似乎在使用 SetWindowLongPtr 和 GetWindowLongPtr 方面是正确的。所以,你可以这样使用它:

LRESULT CALLBACK my_callback(HWND hwnd, UINT ui, WPARAM wp, LPARAM lp) {
    Window * self = reinterpret_cast<Window*>(
        GetWindowLongPtr(hwnd, 0));
    return self->update(hwnd, ui, wp, lp); // handle it.
}

将该函数注册为 wnd-proc 并使用 SetWindowLongPtr 存储 Window 对象的 this 指针。在 WNDCLASSEX 结构中,有一个 cbWndExtra 字段,您可以将 sizeof(Window*) 分配给它,它足以存储仅包含 this指针。然后你可以调用

SetWindowLongPtr(my_hwnd, 0, reinterpret_cast<LONG_PTR>(this));

将 this 指针放入该区域。然后像上面那样接收并委托(delegate)给真正的成员函数。理论上您也可以使用静态成员函数。但你必须要小心。从 C 代码调用静态成员函数可能会导致错误,因为 C 代码和 C++ 代码之间的调用约定可能不同。对于 Windows,这可能不是问题 - 我不知道。所以最好另外检查一下自己。


你尝试的东西是无效的。您尝试返回一个指向函数调用运算符的指针,但调用时没有提供任何对象,除此之外您的转换运算符类型错误。转换运算符返回的类型是函数指针类型,不是成员函数指针类型。最接近的是使用正确的类型:

struct adder;
typedef int (adder::*int_to_int)(int);

struct adder {
    int n_;
    adder (int n) : n_(n) {}
    int operator() (int x) { return x + n_; }
    operator int_to_int () {
        return &adder::operator();
    }
};

现在,您的转换运算符甚至都不在考虑之列,因为它必须这样调用:

adder a(10); cout << (a.*(int_to_int)a)(2); // expected: 12

然后手动像这样:

// note, we just get the member function pointer using the conversion operator.
// Nothing is related to the actual temporary adder object. 
int_to_int i = adder(5);
cout << (adder(10).*i)(2); // expected: 12

通常的函数调用语法无法解决这个问题。简而言之,您尝试的是不可能的。

我认为另一个问题是,您到底为什么要这样做?我认为当我们知道最初的问题是什么时,我们可以更好地帮助您。如果你想让它看起来和工作起来像一个函数调用,你根本不需要任何转换运算符:

struct adder {
    int n_;
    adder (int n) : n_(n) {}
    int operator() (int x) { return x + n_; }
};

adder a(10); cout << a(2); // expected: 12

关于c++ - 在用 C++ 编写 win32 api 包装器时,如何将此指针传递给静态函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/412183/

相关文章:

c++ - GCC 7 没有选择正确的类型特征特化

c++ 缺少 vtable 错误

c++ - 在 Windows 中使用 C++ 检查用户是否是本地计算机上的管理员

java - 使用 WM_COPYDATA 在使用 JNI 的 Java 应用程序之间发送字符串消息

function - gitlab ci 脚本功能失败时屏蔽 exit 1

C++ 位集算法

php - 从 php system() 函数获取完整输出

windows - Win32 工具提示在 Commctl 6 中消失,永远不会重新出现

java - 让 Asynctask 开始工作

function - 如何确定 Haxe 中函数接受的参数数量?