0

我创建了这个帐户来问一个问题,因为我现在很迷茫,找不到答案。我不确定我正在尝试做的事情是否可能,或者我可能采取了不正确的方法。

我正在为异步套接字编写一个 Windows 套接字包装器类,主要是因为我不必再次编写此代码,并且我试图将函数指针作为成员变量存储在我的网络代码类中,它指向一个 Windows 事件处理程序在指向其他地方的应用程序的正常 win32 消息泵内调用。基本上,我正在尝试创建一个程序员定义的回调函数,这样当我将此网络代码类编译成 .dll 时,我就不必再碰它了。

澄清一下,我要做的是,例如,为WM_SOCKET网络代码类内部以外的某个地方编写事件处理程序(这是我定义的 Windows 消息)(因此它可以移植到不同的 win32/C++项目)和主要的win32消息泵之外(所以我WndProc()不会变得绝对庞大)。

我什至不知道要搜索什么,但我找到的所有信息都是关于创建指向成员函数或模板成员的指针,这不是我想要的。

这是我已经尝试编写的代码(仅相关位),这给我带来了问题。我可能在这里搞砸了。

//// Sockets.h
class NetworkConnection
{
private:
    void (*WMSocketFunction)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

public:
    void HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    void registerSocketFunction( void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)));
};

//// Sockets.cpp
#include "Sockets.h"

void NetworkConnection::registerSocketFunction( void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)))
{
    WMSocketFunction = SocketFunction;
};

void NetworkConnection::HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    WMSocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
}

//// Application.cpp
void SocketEventHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    // Do socket stuff here
};

int SetupApp()
{
    NetworkConnection NetConnection;
    NetConnection.registerSocketFunction(&SocketEventHandler);
    return 0;
}

LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch( msg )
    {

    case WM_SOCKET:
        {
            NetConnection.HandleEvents(hwnd, msg, wParam, lParam);
            break;
        }

    case WM_DESTROY:
        {
            ReleaseDevices();
            break;
        }
    case WM_KEYDOWN:
        {
#ifdef _DEBUG
            if (lParam == VK_ESCAPE)
                PostQuitMessage(0);
#endif
        }
    }
    return ::DefWindowProc(hwnd, msg, wParam, lParam);
}

在这里,我将非常感谢您的帮助。我完全不知道为什么这不起作用。

我收到的错误是:

Error   1   error C2440: '=' : cannot convert from 'void *(__cdecl *)(HWND,UINT,WPARAM,LPARAM)' to 'void (__cdecl *)(HWND,UINT,WPARAM,LPARAM)'    sockets.cpp (in function registerSocketFunction)
Error   2   error C2275: 'HWND' : illegal use of this type as an expression     sockets.cpp (in function HandleEvents)
Error   3   error C2146: syntax error : missing ')' before identifier 'hwnd'    sockets.cpp (in function HandleEvents)
Error   4   error C2059: syntax error : ')'    sockets.cpp (in function HandleEvents)
Error   8   error C2664: 'NetworkConnection::registerSocketFunction' : cannot convert parameter 1 from 'void (__cdecl *)(HWND,UINT,WPARAM,LPARAM)' to 'void *(__cdecl *)(HWND,UINT,WPARAM,LPARAM)'    application.cpp

如果您需要任何更好的解释,因为我可能对这个问题的解释很糟糕,请不要犹豫。

我正在使用 Visual Studio 2010,所以我认为我不能使用 std::function 等 C++/11 功能。

4

3 回答 3

4
  1. 从函数指针声明中排除参数名称
  2. 使用 typedef 让代码更干净

    typedef void(*WMSocketFunction_Ptr)(HWND, UINT, WPARAM, LPARAM);
    
    class NetworkConnection
    {
    private:
        WMSocketFunction_Ptr WMSocketFunction;
    
    public:
        void HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
        void registerSocketFunction(WMSocketFunction_Ptr SocketFunction);
    };
    
    void NetworkConnection::registerSocketFunction(WMSocketFunction_Ptr SocketFunction)
    {
        WMSocketFunction = SocketFunction;
    };
    
  3. 更喜欢对裸指针使用 STL 工具:std::function of boost::function

    typedef std::function<void(HWND, UINT, WPARAM, LPARAM)> WMSocketFunction_Ptr;
    
于 2013-10-06T10:05:01.140 回答
2

您必须将函数指针名称括在括号中,如下所示:void (*SocketFunction)(...) 因此,而不是您的方法声明:

void registerSocketFunction( void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)));

你必须写:

void registerSocketFunction( void (*SocketFunction)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam));

还将您的方法主体重写为:

void NetworkConnection::registerSocketFunction( void (*SocketFunction)(HWND, UINT, WPARAM, LPARAM))
{
    WMSocketFunction = SocketFunction;
};

接下来,我认为你的 HandleEvents 还没有完成,你有一个语法错误,我想你想调用指针后面的函数。

void NetworkConnection::HandleEvents(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    WMSocketFunction(hwnd,msg,wParam,lParam);
}
于 2013-10-06T09:45:40.233 回答
1

这是我的怀疑。我认为您声明函数参数SocketFunction的方式registerSocketFunction是错误的。

void NetworkConnection::registerSocketFunction( void (*SocketFunction(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)))

应该,

void NetworkConnection::registerSocketFunction( void (*SocketFunction)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam))

我在 GCC 上进行了类似的测试,它抛出了类似的错误,所以这可能是你的问题。

于 2013-10-06T09:46:11.020 回答