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

C++ Linker error LNK2001 and LNK1120 Winsock2 Lib

本文关键字:LNK1120 Winsock2 Lib LNK2001 链接 错误 C++      更新时间:2023-10-16

我似乎无法摆脱这个编译器错误。

Error   1   error LNK2001: unresolved external symbol "public: __thiscall Socket::Socket(void)" (??0Socket@@QAE@XZ) C:arma-to-socketConsoleApplication5ConsoleApplication5ConsoleApplication5.obj   ConsoleApplication5
Error   2   error LNK1120: 1 unresolved externals   C:arma-to-socketConsoleApplication5ReleaseConsoleApplication5.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;
}

插座.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: %dn", 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(): %ldn", 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: %dn", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
status = 1;
}
statusMsg = ("Bytes Sent: %ldn", 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: %dn", 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 closedn");
else{
statusMsg = ("recv failed: %dn", 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: %dn", 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"+ "";
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的项目。

该错误不是编译器错误,而是链接器错误。两者之间是有区别的,知道区别会让你更清楚眼前的问题。

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

您的代码编译没有问题,因为编译器不关心您调用的函数是否真的存在。只要有函数的声明(就像你在代码中一样),或者函数体位于函数调用之前,编译器就会说"好的,没问题"。

在成功编译之后,链接器现在实际上会尝试查找代码正在调用的函数。如果在其他对象模块或库中找不到该函数,则链接器会向您提供"未解析的外部"错误。如果出现这些错误,请仔细阅读错误消息,因为错误说明正在调用但找不到的函数。

看起来像链接器的官样文章正在发疯——这只是名称混乱,而不是对这种错误的关注。消息的重要部分是类和函数名,以及参数(在本例中为void,表示没有参数)。

我认为您只是错过了函数Socket()的实现。在.cpp中实现Socket(),一切都会正常工作。