1

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

#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) 的行)时,我收到以下错误消息:

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

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

4

3 回答 3

1

考虑到您对 Remus Rusanu 的回复,如果您想要这样做的原因只是为了在不同平台之间进行移植,那么在导入级别进行抽象是做您想做的事情的错误方法。例如,不同平台上外观相似的套接字函数将返回的错误代码各不相同(不仅在它们的 id/编号上,而且在含义和可用性上)。

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

于 2009-09-28T00:07:57.497 回答
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 定义中,尝试使用 using__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
于 2009-09-28T00:05:17.410 回答
0

解决了!感谢大家的帮助。为了解决这个问题,我只是改变了 typedef 如下:

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

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

于 2009-09-28T00:18:20.377 回答