C ++链接器错误LNK2001和LNK1120 Winsock2 Lib

时间:2015-04-20 21:50:50

标签: c++ linker winsock winsock2

我似乎无法动摇这个编译错误。

Error   1   error LNK2001: unresolved external symbol "public: __thiscall Socket::Socket(void)" (??0Socket@@QAE@XZ) C:\arma-to-socket\ConsoleApplication5\ConsoleApplication5\ConsoleApplication5.obj   ConsoleApplication5
Error   2   error LNK1120: 1 unresolved externals   C:\arma-to-socket\ConsoleApplication5\Release\ConsoleApplication5.exe   ConsoleApplication5

据我所知,我已经知道了正确的lib文件:

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

包括我认为我需要的所有内容:

#define WIN32_LEAN_AND_MEAN
#include "stdafx.h"
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string> 

完整源代码:

要调试的控制台应用程序(稍后将在另一个项目中编译为dll): 主cpp文件

// ConsoleApplication5.cpp : Defines the entry point for the console application.
//

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

#include "stdafx.h"
#include <iostream>
#include "Socket.h"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{       
     char myIP[10] = "127.0.0.1";
     Socket mySocket;
     mySocket.Init(*myIP);
     mySocket.Connect();
     mySocket.Send("hello world");

     return 0;
}

socket.h中

#pragma once

#define WIN32_LEAN_AND_MEAN
#include "stdafx.h"
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string> 

// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

#define DEFAULT_BUFLEN 1024
#define DEFAULT_PORT "9999"
using namespace std;
class Socket
{
public:
     Socket();
     Socket(CHAR);
     void Init(CHAR);
     int Connect();
     int Send(string input);
     string Recieve();
     int Disconnect();
     string SendRecieve(string input);
     int getStatus();
     char getStatusMsg();
     ~Socket();
private:
     struct addrinfo *result = NULL,
         *ptr = NULL,
         hints;
     char *sendbuf = "this is a test";
     char recvbuf[DEFAULT_BUFLEN];
     int iResult;
     int recvbuflen = DEFAULT_BUFLEN;
     int status;
     CHAR statusMsg;
     SOCKET ConnectSocket;
     CHAR addressChar;
     CHAR *addressPtr;
     WSADATA wsaData;
};

Socket.cpp:

#include "stdafx.h"
#include <string> 
#include "Socket.h"

Socket::Socket(CHAR address){
    Init(address);

}



void Socket::Init(CHAR address)
{
    addressChar = address;
    addressPtr = &addressChar;

    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL,
        *ptr = NULL,
        hints;
    char *sendbuf = "this is a test";
    iResult = getaddrinfo(addressPtr, DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
        statusMsg = ("getaddrinfo failed: %d\n", iResult);
        WSACleanup();
        status = 1;
    }

    // Attempt to connect to the first address returned by
    // the call to getaddrinfo
    ptr = result;

    // Create a SOCKET for connecting to server
    ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
        ptr->ai_protocol);
    if (ConnectSocket == INVALID_SOCKET) {
        statusMsg = ("Error at socket(): %ld\n", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
        status = 1;
    }
    status = -1;
}

int Socket::Connect() {
    iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        closesocket(ConnectSocket);
        ConnectSocket = INVALID_SOCKET;
    }
    // Should really try the next address returned by getaddrinfo
    // if the connect call failed
    // But for this simple example we just free the resources
    // returned by getaddrinfo and print an error message

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        //statusMsg = "Unable to connect to server!";
        WSACleanup();
        status = 1;
    }
    if (status = 1){
        return 1;
    }
    else {
        return 0;
    }

};

int Socket::Send(string input){
    char *sendbuf = (char*)input.c_str();
    // Send an initial buffer
    iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
    if (iResult == SOCKET_ERROR) {
        statusMsg = ("send failed: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        status = 1;
    }

    statusMsg = ("Bytes Sent: %ld\n", iResult);

    // shutdown the connection for sending since no more data will be sent
    // the client can still use the ConnectSocket for receiving data
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        statusMsg = ("shutdown failed: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        status = 1;
    }
    if (status = 1){
        return 1;
    }
    else {
        return 0;
    }
};

string Socket::Recieve() {
    string rtn = "";
    // Receive data until the server closes the connection
    do {
        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if (iResult > 0){
            string rtn = recvbuf;
        }
        //else if (iResult == 0)
        //statusMsg = ("Connection closed\n");
        else{
            statusMsg = ("recv failed: %d\n", WSAGetLastError());

        }
    } while (iResult > 0);
    return rtn;

};

int Socket::Disconnect(){
    // shutdown the send half of the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        //printf("shutdown failed: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        status = 1;
    }
    return 0;

};

string Socket::SendRecieve(string input){
    Send(input);
    return Recieve();

};

int Socket::getStatus(){

    return status;
}
char Socket::getStatusMsg(){
    return statusMsg;
}
Socket::~Socket()
{
    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    status = 0;
};

注意:当在预期的目标项目中并编译为dll时,它编译时没有错误,但在运行时崩溃。

目标项目的主要文件:

// threaded_example.cpp : Defines the exported functions for the DLL application. 
// original threading arma plugin from http://killzonekid.com
//

#define WIN32_LEAN_AND_MEAN
#include "stdafx.h" 
#include <string> 
#include <unordered_map> 
#include <thread> 
#include <mutex> 
#include <atomic> 
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>


#include "Socket.h"


// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")


#define DEFAULT_BUFLEN 1024
#define DEFAULT_PORT "9999"


//todo: pass parameters

//todo multi part returns




// source: https://msdn.microsoft.com/en-us/library/windows/desktop/ms737591%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396

using namespace std;

//string socketClient(string input);

char address[] = "127.0.0.1";


Socket mySocket( *address);

struct Data
{
    bool ready = false;
    string params = "";
    string result = "";
};

unordered_map<long int, Data> tickets;
mutex mtx;
atomic<bool> worker_working(false);
long int id = 0;// global ticket id 
long int cur_id = 0; // current ticket id 


extern "C"
{
    __declspec (dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function);
}

void worker()
{
    while (worker_working = id > cur_id) // next ticket exists? 
    {
        string output;
        mtx.lock();
        Data ticket = tickets[++cur_id];// copy ticket 
        mtx.unlock();

        string input = ticket.params; // get input 
        //string output = "output: " + input; // process input 
        //Sleep(10); //sleep for 0.01 sec (FOR TESTING PURPOSES ONLY) 
        switch (mySocket.getStatus()){

        case -1:
            mySocket.Connect();


        case 0:
            output = mySocket.SendRecieve(input);
            break;

        case 1:
            output = mySocket.getStatusMsg();
                if (output == ""){
                    output = "an uknown eror occured";
                }
            break;


        };
        //string output = socketClient(input);
        //code here
        //output = output +"\n"+ "\0";

        ticket.result = output; // prepare result 
        ticket.ready = true; // notify about result 
        mtx.lock(); tickets[cur_id] = ticket; // copy back the result 
        mtx.unlock();
    }
}


void __stdcall RVExtension(char *output, int outputSize, const char *function)
{
    if (!strncmp(function, "r:", 2)) // detect checking for result 
    {
        long int num = atol(&function[2]); // ticket number or 0
        if (tickets.find(num) != tickets.end()) // ticket exists 
        {
            mtx.lock();
            if (tickets[num].ready) // result is ready 
            {
                strncpy_s(output, outputSize, tickets[num].result.c_str(), _TRUNCATE); // result 
                tickets.erase(num); // get rid of the read ticket 
                mtx.unlock();
                return;
            }
            mtx.unlock();
            strncpy_s(output, outputSize, "WAIT", _TRUNCATE);// result is not ready 
            return;
        }
        strncpy_s(output, outputSize, "EMPTY", _TRUNCATE); // no such ticket 
    }
    else if (!strncmp(function, "s:", 2)) // detect ticket submission 
    {
        Data data;
        data.params = string(&function[2]); // extract params 
        mtx.lock(); tickets.insert(pair<long int, Data>(++id, data)); // add ticket to the queue 
        mtx.unlock();
        if (!worker_working) // if worker thread is finished, start another one 
        {
            worker_working = true;
            thread worker(worker);
            worker.detach(); // start parallel process 
        }
        strncpy_s(output, outputSize, to_string(id).c_str(), _TRUNCATE); // ticket number 
    }
    else
    {
        strncpy_s(output, outputSize, "INVALID COMMAND", _TRUNCATE); // other input 
    }
}

我的经验主要是使用python和PHP。这是我第一个使用c ++和VS2013的正确项目。

2 个答案:

答案 0 :(得分:3)

错误不是编译器错误,而是链接器错误。两者之间存在差异,知道差异将使您更加了解手头的问题。

链接器错误表明它找不到实现的Socket::Socket(void)函数。查看代码,似乎缺少Socket的无参数(默认)构造函数的实现。

您编写的代码没有问题,因为编译器并不关心您调用的函数是否确实存在。只要函数声明(就像在代码中一样),或函数体位于函数调用之前,编译器就会说“好了,没问题&#34;。” p>

编译成功后,链接器现在实际上会尝试查找代码调用的函数。如果它无法在其他对象模块或库中找到该函数,那么链接器会为您提供&#34;未解析的外部&#34;错误。如果您收到这些错误,请仔细阅读错误消息,因为错误是说明正在调用哪些函数,但无法找到。

看起来像链接器的gobbledy-gook变得疯狂 - 这只是名称错误而不是对此类错误的关注。消息的重要部分是类和函数名称,以及参数(在本例中为void,表示没有参数)。

答案 1 :(得分:0)

我认为你只是错过了函数Socket()的实现。在你的.cpp中实现Socket(),一切都应该有效。