Я создал эту учетную запись, чтобы задать вопрос, потому что сейчас я довольно потерян, и я не смог найти ответ. Я не уверен, что то, что я пытаюсь сделать, даже возможно, или, возможно, я использую неправильный подход.
Я пишу класс оболочки стека Windows для асинхронных сокетов, в основном, поэтому мне больше не нужно писать этот код, и я пытаюсь сохранить указатель на функцию как переменную-член внутри моего класса netcode, которая указывает на обработчик событий Windows, который вызванный внутри стандартного насоса сообщений win32 приложения, который указывает в другом месте. В принципе, я пытаюсь создать определенную программистом функцию обратного вызова, так что, когда я скомпилирую этот класс netcode в.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, поэтому я не думаю, что могу использовать функции C++/11, такие как std :: function.
Вы должны заключить имя указателя функции в скобки следующим образом: 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);
}
Использовать 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;
};
Предпочитаете использовать объекты STL для голой указатели: std :: function boost :: function
typedef std::function<void(HWND, UINT, WPARAM, LPARAM)> WMSocketFunction_Ptr;
std::tr1::function
. Если ваш компилятор не поддерживает его, вы можете использовать boost :: function.
Вот мое подозрение. Я думаю, что способ, которым вы объявили аргумент функции 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, и он выбросил аналогичную ошибку, так что это может быть вашей проблемой.
(*WMSocketFunction)(hwnd,msg,wParam,lParam);
?