使用LoadLibrary和GetProcAddress调用WinSock函数

时间:2009-09-27 23:16:43

标签: c++ winsock loadlibrary winsock2 getprocaddress

基本上我有一个像这样的头文件:

#if WIN32
typedef DWORD (WSAAPI *SocketStartup) (WORD wVersionRequested, LPWSADATA lpWSAData);
typedef SOCKET (WINAPI *MakeSocket)(IN int af,    IN int type,    IN int protocol,    IN LPWSAPROTOCOL_INFOW lpProtocolInfo,    IN GROUP g,    IN DWORD dwFlags    );
typedef DWORD (WINAPI *SocketSendFunc) (IN SOCKET s,__in_bcount(len) const char FAR * buf, IN int len,IN int flags);
typedef DWORD (WINAPI *GetLastSocketErrorFunc)();
typedef DWORD (WINAPI *ShutdownSocketFunc)(SOCKET hSocket, int how);
typedef DWORD (WINAPI *CloseSocketFunc)(SOCKET hSocket);
#endif

然后我做这样的事情:

    SocketStartup* start = (SocketStartup*)GetProcAddress(socketLib,"WSAStartup");
    getLastSocketError = (GetLastSocketErrorFunc*)GetProcAddress(socketLib,"WSAGetLastError");
    closeSocket = (CloseSocketFunc*)GetProcAddress(socketLib,"closesocket");
    shutdownSocket = (ShutdownSocketFunc*) GetProcAddress(socketLib,"shutdown");
    socketSend = (SocketSendFunc*) GetProcAddress(socketLib, "send");
    if(start == 0 || getLastSocketError == 0 || closeSocket == 0 || shutdownSocket == 0
        || socketSend == 0)
    {
        printf("[!] Failed to find entry points in Ws2_32.dll. Error Code: %d\n", GetLastError());
        CloseLibraries();
        ErrorExit();
    }
    WSADATA wsdata;

    //ZeroMemory(&wsdata,sizeof(wsdata));
    printf("error: %d\n", GetLastError());
    WORD test = MAKEWORD(1,1);
    int result = (*start)(test, &wsdata);
    return result == 0;

但是,当我调用此函数时(带有(* start)(test,& wsdata)的行)我收到此错误消息:

  

0x7868146a处的未处理异常   sockets.exe:0xC0000005:访问   冲突。

我尝试更改调用约定(__cdecl,WINAPI,WSAAPI),但它始终以相同的错误消息结束。

3 个答案:

答案 0 :(得分:1)

考虑到你对Remus Rusanu的回复,如果您想要这样做的原因只是为了在不同平台之间移植,那么在导入级别抽象是做错的方式。例如,类似外观的套接字在不同平台上运行的错误代码将会返回(不仅仅是它们的id / number,而是意义和可用性)。

我以前做过这个,并且在平台特定的套接字函数(或必要的多个函数)周围使用短包装函数,转换错误消息等,以便它们对我的应用程序是统一的WRT;我为每个平台都有一个单独的文件/实现。它运作良好。

答案 1 :(得分:0)

鉴于您正在和/或未使用的预处理器定义,编译时“WINAPI”的值是多少?我问,因为windef.h包含奇怪的东西,比如......

#ifdef _MAC
#define CALLBACK    PASCAL
#define WINAPI      CDECL
#define WINAPIV     CDECL
#define APIENTRY    WINAPI
#define APIPRIVATE  CDECL
#ifdef _68K_
#define PASCAL      __pascal
#else
#define PASCAL
#endif
#elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
#define CALLBACK    __stdcall
#define WINAPI      __stdcall
#define WINAPIV     __cdecl
#define APIENTRY    WINAPI
#define APIPRIVATE  __stdcall
#define PASCAL      __stdcall
#else
#define CALLBACK
#define WINAPI
#define WINAPIV
#define APIENTRY    WINAPI
#define APIPRIVATE
#define PASCAL      pascal
#endif

在您的typedef定义中,使用__stdcall代替WINAPI进行尝试。


修改

当我在我的机器上运行以下代码时,它不会崩溃,并且socketStartup调用返回0:

#include "windows.h"

typedef DWORD (PASCAL FAR *SocketStartup) (WORD wVersionRequested, LPWSADATA lpWSAData);

int main(int argc, char* argv[])
{
    HMODULE hModule = LoadLibrary("wsock32.dll");
    SocketStartup socketStartup = (SocketStartup)GetProcAddress(hModule, "WSAStartup");
    WSADATA wsdata;

    WORD test = MAKEWORD(1,1);
    int result = (*socketStartup)(test, &wsdata);
    return result == 0;
    return 0;
}

使用Visual C ++ 2008,使用以下编译器命令行:

/Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc90.pdb" /W3 /nologo /c /ZI /TP /errorReport:prompt

答案 2 :(得分:0)

解决!感谢大家的帮助。为了解决这个问题,我刚刚更改了typedef,如下所示:

typedef int (WSAAPI SocketStartup)(    IN WORD wVersionRequested,    OUT LPWSADATA lpWSAData    );

基本上我从Winsock2.h复制并粘贴:P