将类成员回调从 __stdcall 转换为 DWORD_PTR

Posted

技术标签:

【中文标题】将类成员回调从 __stdcall 转换为 DWORD_PTR【英文标题】:convert Class member callback from __stdcall to DWORD_PTR 【发布时间】:2010-01-03 13:05:23 【问题描述】:

我正在尝试使用类成员作为回调,但编译器给了我以下错误:

Error 2 error C2440: 'type cast' : cannot convert from 'void (__stdcall CWaveIn::* )(HWAVEIN,UINT,DWORD_PTR,DWORD_PTR,DWORD_PTR)' to 'DWORD_PTR'

是否可以通过这种方式将成员函数用作回调?以及如何将stdcall成员指针转换为winapi函数请求的DWORD_PTR?

class CWaveIn

private:
    void CALLBACK WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
;

void CWaveIn::Open() 

    (...)
    MMRESULT result = ::waveInOpen(&hWaveIn, currentInputDeviceId, waveFormat, (DWORD_PTR)CWaveIn::WaveInProc, 0, CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT);

【问题讨论】:

【参考方案1】:

你不能直接传入类方法。

这是正确的方法:

class CWaveIn

private:
    static void CALLBACK staticWaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
    
        CWaveIn* pThis = reinterpret_cast<CWaveIn*>( dwParam1 );
        pThis->WaveInProc( ... );
    
    void WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
    
       // your code
    
;

void CWaveIn::Open() 

     (...)
     MMRESULT result = ::waveInOpen(&hWaveIn, currentInputDeviceId, waveFormat, CWaveIn::staticWaveInProc, this, CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT);

【讨论】:

很好,但是 WaveInProc 将能够访问成员数据?因为它是从静态上下文中调用的,所以这不会引发访问冲突吗? waveInOpen 被传递一个函数指针和一个应用程序定义的上下文值,该值被传递回回调函数。在这种情况下,“this”作为上下文值传递,并且在回调的静态变体中,被强制转换回 CWaveIn 实例,从而允许调用非静态 WaveInProc。【参考方案2】:

一般的,虽然绝不是完美的,解决方案是使函数静态。

【讨论】:

【参考方案3】:

这样可以使用成员函数作为回调吗?

没有。他们有不同的签名。除了列出的参数之外,成员函数还需要一个隐式的 this 参数。不能作为非成员函数调用。

如何将stdcall成员指针转换为winapi函数请求的DWORD_PTR?

你不能。您必须编写一个包装函数来用作回调。它应该是静态成员函数或非成员函数。

【讨论】:

好的,所以我能做的最好的就是将我的数据声明为全局数据以供我的回调使用? 或多或少。指向对象的指针必须可以从非成员上下文访问。这可能是通过一个全局指针或一个包含指向多个对象的指针的全局映射。或者,API 可能允许您将一些用户定义的数据传递给回调函数,例如对象指针。

以上是关于将类成员回调从 __stdcall 转换为 DWORD_PTR的主要内容,如果未能解决你的问题,请参考以下文章

如何运用c++里的“__stdcall”?

将C stdcall接口方法中的变量参数转换为Delphi

为 __stdcall 函数指针提供比预期更多的参数

异步回调函数

从 Objective C 将回调/闭包转换为 Swift

将回调参数从 C# 传递到非托管 C++